Typescript

Component cannot be used as a JSX component Its return type Element is not a valid JSX element

19 September 2026 · 10 min read

Component cannot be used as a JSX component Its return type Element is not a valid JSX element

Encountering the frustrating error “Component cannot be used as a JSX component. Its return type ‘Element[]’ is not a valid JSX element” can be a significant roadblock in React development. This error typically arises when a React component, designed to render JSX, inadvertently returns an array of elements directly instead of a single JSX element or a fragment. Understanding the nuances of JSX, component composition, and return types is crucial for resolving this issue and ensuring smooth application performance. In this comprehensive guide, we’ll dissect the causes behind this common error, explore effective solutions, and provide best practices to prevent it from derailing your development workflow. We’ll also cover potential TypeScript implications and how to correctly define component return types.

Understanding the “Component Cannot Be Used as a JSX Component” Error

The core issue stems from JSX’s expectation that a component should return a single root element (or a fragment, which acts as a single root). React’s rendering engine needs a clear, structured tree to efficiently update the DOM. Returning an array directly violates this principle. Imagine trying to build a house with multiple foundations – it wouldn’t be structurally sound. Similarly, JSX components require a single entry point for rendering. This single entry point allows React to manage and update the component efficiently. When you attempt to render multiple elements without a parent container, React becomes confused about how to handle the updates and throws this error.

Several factors can contribute to this error. A common mistake is forgetting to wrap multiple elements within a parent

or a React Fragment (<> >). Another possibility is accidentally mapping an array of data directly into JSX elements without wrapping them within a container. TypeScript's type checking, while helpful, can sometimes mask the underlying problem if the return type of the component is not correctly defined. Incorrectly typed components can lead to unexpected behavior at runtime. For example, if a function is expected to return a single JSX element but returns an array, the TypeScript compiler might not always catch this if the return type is overly broad. Consider this scenario: You're building a list of items. You map over an array of data and generate a list item (
  1. ) for each item. If you directly return the array of

  2. elements from your component, you’ll encounter this error. The correct approach is to wrap the

  3. elements within an unordered list () element, providing the necessary single root element. This ensures that the JSX structure is valid and React can correctly render the list. Debugging these issues often involves carefully examining the component’s return statement and identifying any instances where multiple elements are being returned without a parent wrapper. Common Causes and Solutions

    Let’s delve into the most prevalent causes of this error and explore practical solutions. Often, the fix is as simple as wrapping your returned elements, but understanding the underlying reasons is key to preventing future occurrences. Incorrect component return types is a major cause, especially when working with TypeScript.

    1. Returning an Array of Elements Directly: This is the most common culprit. As mentioned earlier, JSX expects a single root element. Returning an array violates this rule. The solution is to wrap the array within a parent element like a

    or a React Fragment (<> >). React Fragments are generally preferred because they don't introduce unnecessary DOM nodes. **2. Incorrect Mapping:** When using .map() to render a list of elements, ensure the mapped elements are wrapped within a parent element. For example, if you are mapping over an array of user data to create a list of user cards, wrap the generated cards within a
    or a element. **3. TypeScript Type Issues:** TypeScript's type system can sometimes be misleading. Ensure your component's return type is correctly defined. If a component is meant to return a single JSX element, its return type should reflect that (e.g., React.ReactNode). If it conditionally returns null, the return type should be React.ReactNode | null. The following example uses a third-party resource to explain ReactNode: [React Rendering Elements](https://legacy.reactjs.org/docs/rendering-elements.html). Incorrectly typed components can result in runtime errors that are difficult to debug. When you have explicit types, TypeScript can catch many errors before runtime. You should always strive to have accurate and detailed types for your components.

    Best Practices to Avoid the Error

    Prevention is better than cure. Implementing these best practices can significantly reduce the likelihood of encountering the “Component cannot be used as a JSX component” error. These practices promote cleaner, more maintainable, and less error-prone code. Consistently applying these techniques will save you debugging time and improve your overall development experience.

    • Always Wrap Multiple Elements: Make it a habit to always wrap multiple JSX elements within a parent element or React Fragment. This is the single most effective way to avoid this error.

    • Use React Fragments: Favor React Fragments (<> >) over

      elements when you don’t need a semantic container. Fragments avoid adding unnecessary nodes to the DOM, improving performance. Consider using a linter rule that enforces a single root element in JSX components. ESLint with the appropriate React plugin can automatically detect and flag instances where multiple elements are returned without a wrapper. Another helpful practice is to write unit tests for your components that specifically check for the correct return type and structure. These tests can catch errors early in the development process before they become more difficult to debug. A linter rule like this is outlined on the ESLint documentation here: ESLint. Consider using TypeScript to enhance type safety and catch potential errors during development. A properly configured TypeScript setup can identify many instances where a component is returning an incorrect type, including arrays of elements instead of a single root element.

      Here’s an example of how to fix the error:

      1. Identify the component causing the error.

      2. Examine the component’s return statement.

      3. If the component returns an array of elements directly, wrap the array within a parent element (e.g.,
        or <>). 2. Test the component to ensure the error is resolved and the rendering is correct. TypeScript Considerations

        TypeScript can be a powerful ally in preventing this error, but it requires careful configuration and understanding. Leveraging TypeScript’s type system effectively can significantly improve the robustness and reliability of your React components. It allows you to define precise types for your component props, state, and return values, enabling the compiler to catch many potential errors before runtime. TypeScript, when used correctly, adds a layer of safety and predictability to your React codebase.

        Ensure your component’s return type is accurately defined. For example, if a component returns JSX, its return type should be React.ReactNode. If it conditionally returns null, the return type should be React.ReactNode | null. When using TypeScript, be mindful of the difference between React.ReactElement and React.ReactNode. React.ReactElement represents a specific JSX element, while React.ReactNode is a broader type that includes elements, strings, numbers, and other renderable values. It is important to choose the appropriate type to accurately reflect what your component returns.

        Here is an example of using Typescript with a component:

        typescript interface MyComponentProps { items: string[]; } const MyComponent: React.FC = ({ items }) => { return ( <> {items.map((item) => ( 2. {item} ))} > ); };
        Infographic here
        FAQ

        Why does JSX require a single root element?
        JSX requires a single root element because React's virtual DOM needs a clear, structured tree to efficiently update the actual DOM. A single root element provides this structure.
        What is a React Fragment and when should I use it?
        A React Fragment (<> >) is a way to group multiple elements without adding an extra node to the DOM. Use it when you need to return multiple elements from a component but don't want to introduce an unnecessary wrapper element.
        How can TypeScript help prevent this error?
        TypeScript can help by enforcing type safety and ensuring that your component's return type matches what it actually returns. Properly defined return types can catch instances where a component is returning an array of elements instead of a single root element. This StackOverflow thread discusses React Fragments and the use of Typescript: [React Fragments](https://stackoverflow.com/questions/39277306/what-is-the-use-of-react-fragments).
        Mastering these concepts and adopting these best practices will significantly improve your React development workflow and help you avoid the frustrating "Component cannot be used as a JSX component. Its return type 'Element\[\]' is not a valid JSX element" error. By understanding the underlying principles of JSX and component composition, you can write cleaner, more maintainable code and build robust and reliable React applications. Keep practicing and experimenting, and you'll become more proficient at handling these common challenges.

        Question & Answer :
        The following error occurs in the Todos component inside the TodoApp.tsx:

        'Todos' cannot be used as a JSX component. Its return type 'Element[]' is not a valid JSX element. Type 'Element[]' is missing the following properties from type 'Element': type, props, key 
        

        Corresponding files:

        TodoApp.tsx

        function TodoApp() { return ( <Body> <AppDiv> <Form /> <Todos /> <Footer /> </AppDiv> </Body> ); } 
        

        Todos.tsx

        function Todos(): JSX.Element[] { const todos = useSelector((state: RootState) => state.todos); const footer = useSelector((state: RootState) => state.footer); if (footer.hideAll) { if (footer.showCompleted) { return todos .filter((todo) => !todo.completed) .map((todo: any) => ( <> <ul> <Todo todo={todo} /> </ul> </> )); } return todos.map((todo) => ( <> <div> <Todo todo={todo} /> </div> </> )); } return todos.map(() => ( <> <div></div> </> )); } 
        

        Todo.tsx

        type Todo = { todo: TodoProps; }; const Todo = ({ todo }: Todo) : JSX.Element => { const [isEditing, edit] = useState<boolean>(false); const dispatch = useDispatch(); if (!isEditing) { return ( <TodoDiv> <Li key={todo.id} completed={todo.completed} onClick={() => dispatch(completeTodo(todo.id))} // style={{ // textDecoration: todo.completed ? "line-through" : "none" // }} > {todo.text} </Li> <TodoBttns> <Button edit onClick={() => edit(!isEditing)}> <img src={editBttn} alt="Edit Button" /> </Button> <Button delete onClick={() => dispatch(deleteTodo(todo.id))}> <img src={deleteBttn} alt="Delete Button" /> </Button> </TodoBttns> </TodoDiv> ); } else { return ( <FormEdit> <InputForm key={todo.id} {...{ todo, edit }} /> </FormEdit> ); } }; 
        

        and the TodoProps interface is defined as follows

        interface TodoProps { text: string; completed: boolean; id: string; } 
        

        I have tried fixing it by wrapping the map of items with fragments, but the error is still thrown. The only thing that as of now is fixing the issue is declaring at the top of Todos.tsx the function as any: function Todos(): any

        As a side note: I’m using StyledComponents, but I don’t think the issue is related to the library.

        A component needs to return a single root element. You can use fragments to package an array of elements as a single element, by using the fragment as that single root element.

        So this does nothing:

        function Todos(): JSX.Element { return todos.map(todo => ( <> <li>{todo.task}</li> </> ) } 
        

        Because it’s now returning an array of [<><li/></>, <><li/></>, ...]. That fragment needs to be the single root element.

        You need to use the fragment like this:

        function Todos(): JSX.Element { return <>{ todos.map(todo => <li>{todo.task}</li>) }</> } 
        

        You nest all returned JSX in one single fragment.

        Using that pattern you may end up with somehting like this:

        function Todos(): JSX.Element { const todos = useSelector((state: RootState) => state.todos); const footer = useSelector((state: RootState) => state.footer); if (footer.hideAll) { if (footer.showCompleted) { return <>{ todos .filter((todo) => !todo.completed) .map((todo: any) => ( <ul> <Todo todo={todo} /> </ul> )) }</> } return <>{ todos.map((todo) => ( <div> <Todo todo={todo} /> </div> )) }</> } return <>{ todos.map(() => ( <div></div> )) }</> } // Works without error <Todos /> 
        

        Note how each return statement returns just one JSX.Element: the fragment.

        Playground