I'm learning Typescript-react and I'm stuck in this error Type '({ items }: PropsWithChildren<TodoProps>) => Element[]' is not assignable to type 'FunctionComponent<TodoProps>'
and I am lost on this.
Complete error:
Type '({ items }: PropsWithChildren<TodoProps>) => Element[]' is not assignable to type 'FunctionComponent<TodoProps>'.
Type 'Element[]' is missing the following properties from type 'ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<any, any, any>)>': type, props, key
Link for code: sandbox repo.
Error happens on the declaration of TodoList
function within the TodoList.tsx
file.
Any help is appreciated. Cheers!
Code:
import React from "react";
interface Todo {
id: number;
content: string;
completed: boolean;
}
interface TodoProps {
items: Todo[];
}
// v------v here is error
const TodoList: React.FC<TodoProps> = ({ items }) => {
return items.map((item: Todo) => <div key={item.id}>{item.id}</div>);
};
export default TodoList;
Element[]' is not assignable to type FunctionComponent" occurs when we try to return an array of elements from a function component. To solve the error, wrap the array of elements into a React fragment.
By invoking them between the opening and closing tags of a JSX element, you can use React children for entering data into a component. The React children prop is an important concept for creating reusable components because it allows components to be constructed together.
To pass a function as props in React TypeScript: Define a type for the function property in the component's interface. Define the function in the parent component. Pass the function as a prop to the child component.
From the sounds of things, it will eventually be deprecated in favor of the naming React. FunctionComponent once React 18 is released.
Argument of type 'Element' is not assignable to parameter of type 'ReactElement<any> []'. Property 'length' is missing in type 'Element'. I've currently tried these versions of react and react-dom:
Type 'Element []' is missing the following properties from type 'Element': type, props, key
All props defined in propTypes are optional. That is the default from library prop-types. Why do we need to infer types from propTypes in LibraryManagedAttributes?
The "Type 'HTMLElement | null' is not assignable to type" error occurs when a possibly null value is assigned to something that expects an element. To solve the error, use a non-null assertion or a type guard to verify the value is a an element before the assignment. This is the html code for the examples in this article. Copied!
Yeah, the error may sound a bit confusing - in essence it says that you can only return a single ReactElement
or its equivalent JSX.Element
in the function component definition, enforced by React.FC
type.
React Fragments solve this limitation, so you can write TodoList
in the following manner:
interface TodoProps {
items: Todo[];
}
const TodoList: React.FC<TodoProps> = ({ items }) => (
<React.Fragment>
{items.map((item: Todo) => (
<div key={item.id}>{item.id}</div>
))}
</React.Fragment>
);
Short form:
const TodoList: React.FC<TodoProps> = ({ items }) => (
<>
{items.map(({ id }) => <div key={id}>{id}</div>)}
</>
);
By the way: With pure JS, both class and function components can return multiple elements in an array as render output. Currently, TS has a type incompatibility for returned arrays in function components, so Fragments provide a viable workaround here (in addition to type assertions).
I've encountered a similar error. Eventually I noticed that I'd renamed the file incorrectly from .js to .ts instead of to .tsx when converting a component to a FunctionComponent with TypeScript.
I also got this error when I was trying to return children
props from my Loading
component like below.
const { loading, children } = props;
return loading ? <p>Loading ... </p> : children;
Then i realize that React is expecting only one return value(1 parent component) from its render
method. Therefore I wrapped children props with React.Fragment
which is denoted by <></>
and that solves my problem. Below is my Loading
component sample, hope that helps someone else.
import { FunctionComponent } from "react";
interface ILoadingProps {
loading: boolean;
}
export const Loading: FunctionComponent<ILoadingProps> = (props) => {
const { loading, children } = props;
return loading ? <p>Loading ... </p> : <>{children}</>;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With