Skip to content

Fixing "Element[] is not a valid JSX element" Error in React TypeScript

Problem Statement

When working with React and TypeScript, you may encounter the error:

'ComponentName' 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

This error typically occurs when a component returns an array of JSX elements instead of a single JSX element, which violates React's requirement that components must return a single root element.

Root Cause Analysis

The core issue originates from how React components handle their return values. In JavaScript/TypeScript, when you use array.map() to render multiple elements, it returns an array of JSX elements. However, React expects components to return a single JSX element (which can contain multiple child elements).

Primary Solution: Use Fragments

The most straightforward solution is to wrap your mapped elements in a React Fragment (<></> or <React.Fragment></React.Fragment>):

tsx
function Todos(): JSX.Element {
  const todos = useSelector((state: RootState) => state.todos);
  
  return (
    <>
      {todos.map((todo) => (
        <div key={todo.id}>
          <Todo todo={todo} />
        </div>
      ))}
    </>
  );
}

Key Points

  • The fragment (<>...</>) acts as a single parent element
  • Each mapped element still needs a unique key prop
  • The return type remains JSX.Element instead of JSX.Element[]

Complete Solution for the Original Problem

Applying this pattern to the original Todos component:

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) => (
              <ul key={todo.id}>
                <Todo todo={todo} />
              </ul>
            ))}
        </>
      );
    }
    return (
      <>
        {todos.map((todo) => (
          <div key={todo.id}>
            <Todo todo={todo} />
          </div>
        ))}
      </>
    );
  }

  return (
    <>{todos.map((todo) => <div key={todo.id} />)}</>
  );
}

Alternative Solutions and Edge Cases

TypeScript Configuration Issues

In some cases, the error might be caused by TypeScript configuration or version conflicts:

json
// tsconfig.json
{
  "compilerOptions": {
    "jsx": "react-jsx",
    "paths": {
      "react": ["./node_modules/@types/react"]
    }
  }
}

Version Conflicts

If you've recently upgraded React, ensure your @types/react and @types/react-dom versions are compatible:

json
// package.json
{
  "resolutions": {
    "@types/react": "^17.0.2",
    "@types/react-dom": "^17.0.2"
  }
}

Common Pitfalls

  1. Missing return statements: Ensure all code paths return a valid JSX element
  2. Switch statements without default: Always include a default return in switch cases
  3. Incorrect import statements: Verify you're using the correct import syntax for each package

Clean Installation Solution

If configuration changes don't resolve the issue, try a clean installation:

bash
rm -rf node_modules package-lock.json
npm install

Best Practices

  1. Always use fragments when returning multiple elements from a component
  2. Provide unique keys for each element in arrays
  3. Keep TypeScript dependencies updated and consistent
  4. Use React.FC type for functional components when appropriate:
tsx
const Todo: React.FC<{ todo: TodoProps }> = ({ todo }) => {
  // component implementation
};

Conclusion

The "Element[] is not a valid JSX element" error is a common TypeScript/React issue with multiple potential solutions. Start with the fragment wrapping approach, ensure proper TypeScript configuration, and verify package version compatibility if the problem persists.

By following React's requirement of returning single root elements and maintaining consistent type definitions, you can avoid this error and build more robust React applications with TypeScript.