Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type '({ items }: PropsWithChildren<TodoProps>) => Element[]' is not assignable to type 'FunctionComponent<TodoProps>'

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;

like image 594
homosaurus Avatar asked Nov 17 '19 06:11

homosaurus


People also ask

Is not assignable to type FunctionComponent?

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.

How do you use a childrens prop in TypeScript?

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.

How do you pass props in functional component TypeScript?

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.

Is React FC deprecated?

From the sounds of things, it will eventually be deprecated in favor of the naming React. FunctionComponent once React 18 is released.

Is it possible to assign arguments of type'element'to parameter'reactelement<any>[]'?

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:

What properties are missing from type'element[]'in typescript?

Type 'Element []' is missing the following properties from type 'Element': type, props, key

Are all props defined in proptypes optional?

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?

How to solve type 'htmlelement | null' is not assignable to type error?

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!


3 Answers

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).

like image 95
ford04 Avatar answered Oct 22 '22 18:10

ford04


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.

like image 45
Alistair Cooper Avatar answered Oct 22 '22 16:10

Alistair Cooper


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 Loadingcomponent 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}</>;
};

like image 1
chety Avatar answered Oct 22 '22 18:10

chety