I'm new to TypeScript and converting my site from WordPress to Payload and I'm getting an error code that I can't find anywhere to fix. The code works but I would like to have the error message go away.
In my block, I get this error message:
Type 'FC<{ path: string; }>' is not assignable to type '(CustomComponent & PayloadComponent<FieldClientComponent | FieldServerComponent>) | undefined'.
What does this error message mean? Again, the code works but I would like this error to go away.
This error message is at my field:
{
name: 'linkURL',
label: 'URL',
type: 'text',
admin: {
components: {
Field: CustomLinkField, // Use custom React component
},
},
},`
This is my react component:
'use client'; // Add this line
import React, { useState, useEffect } from 'react';
import { useField } from '@payloadcms/ui';
const API_KEY = 'xxxxxx'; // Replace with your actual API key
const CustomLinkField: React.FC<{ path: string }> = ({ path }) => {
const { value, setValue } = useField<string>({ path }); // Get the linkURL value
const { setValue: setJsonValue } = useField<string>({ path: path.replace('linkURL', 'linkOutput') }); // Get the linkOutput field
const [loading, setLoading] = useState(false);
useEffect(() => {
const fetchMetadata = async () => {
if (value && value.startsWith('http')) {
setLoading(true);
try {
const apiUrl = `https://iframe.ly/api/iframely?url=${encodeURIComponent(value)}&api_key=${API_KEY}`;
const response = await fetch(apiUrl);
if (!response.ok) throw new Error('Failed to fetch data');
const json = await response.json();
setJsonValue(JSON.stringify(json, null, 2)); // Store JSON output
} catch (error) {
console.error('Error fetching link metadata:', error);
setJsonValue('Error fetching data');
} finally {
setLoading(false);
}
}
};
fetchMetadata();
}, [value]); // Run effect whenever value (linkURL) changes
return (
<div>
<input
type="text"
value={value || ''}
onChange={(e) => setValue(e.target.value)}
placeholder="Enter URL"
style={{ width: '100%', padding: '8px' }}
/>
{loading && <p>Loading...</p>}
</div>
);
};
export default CustomLinkField;
This is my code on my block (ts) file:
import type { Block } from 'payload';
import CustomLinkField from '../iframely';
export const blockLink: Block = {
slug: 'block-link',
interfaceName: 'blockLink',
labels: {
singular: 'Link',
plural: 'Links',
},
fields: [
{
name: 'linkURL',
label: 'URL',
type: 'text',
admin: {
components: {
Field: CustomLinkField, // Use custom React component
},
},
},
{
name: 'linkOutput',
label: 'JSON Output',
type: 'textarea',
admin: {
readOnly: true, // Prevent manual edits
},
},
],
};
If you explore the definition of type Block
and it's property fields
, it is of type
fields: Field[];
CustomLinkField
is of type Field
You will see that Field
type is declared as follows:
export type Field = ArrayField | BlocksField | CheckboxField | CodeField | CollapsibleField | DateField | EmailField | GroupField | JoinField | JSONField | NumberField | PointField | RadioField | RelationshipField | RichTextField | RowField | SelectField | TabsField | TextareaField | TextField | UIField | UploadField;
If you dig a little further into these definitions e.g. TextField
export type TextField = {
admin?: {
autoComplete?: string;
components?: {
afterInput?: CustomComponent[];
beforeInput?: CustomComponent[];
Error?: CustomComponent<TextFieldErrorClientComponent | TextFieldErrorServerComponent>;
Label?: CustomComponent<TextFieldLabelClientComponent | TextFieldLabelServerComponent>;
} & Admin['components'];
placeholder?: Record<string, string> | string;
rtl?: boolean;
} & Admin;
maxLength?: number;
minLength?: number;
type: 'text';
}
And the Admin
definition
type Admin = {
className?: string;
components?: {
Cell?: PayloadComponent<DefaultServerCellComponentProps, DefaultCellComponentProps>;
Description?: PayloadComponent<FieldDescriptionServerProps, FieldDescriptionClientProps>;
Diff?: PayloadComponent<FieldDiffServerProps, FieldDiffClientComponent>;
Field?: PayloadComponent<FieldClientComponent | FieldServerComponent>;
/**
* The Filter component has to be a client component
*/
Filter?: PayloadComponent;
};
So from the Admin
definition you can see that the Field
property should be of type
Field?: PayloadComponent<FieldClientComponent | FieldServerComponent>;