error TS2786: 'X' cannot be used as a JSX component. Its return type 'ReactNode' is not a valid JSX element.
ID: typescript/ts2786-not-a-jsx-component
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 5 | active | — | — | — |
Root Cause
Almost always caused by multiple versions of @types/react in the dependency tree. Different packages depend on different @types/react versions, causing conflicting JSX element type definitions.
genericWorkarounds
-
90% success Force a single @types/react version with resolutions or overrides
In package.json, add: for npm: "overrides": { "@types/react": "^18.2.0" }, for yarn: "resolutions": { "@types/react": "^18.2.0" }, for pnpm: "pnpm": { "overrides": { "@types/react": "^18.2.0" } }. Then rm -rf node_modules && npm install.Sources: https://docs.npmjs.com/cli/v10/configuring-npm/package-json#overrides
-
82% success Stop using React.FC and type return as React.ReactElement | null
React.FC return type changed between @types/react 17 and 18. Direct function typing is more stable: function MyComponent(props: Props): React.ReactElement | null { ... }. This avoids the FC type definition conflict. -
78% success Add a wrapper component with explicit typing for library components
If the component is from a library with an old @types/react: const Wrapped: React.FC<Props> = (props) => <LibComponent {...props} />; The wrapper component uses your local @types/react, resolving the mismatch.
Dead Ends
Common approaches that don't work:
-
Changing the component's return type to JSX.Element
72% fail
JSX.Element is overly restrictive — it breaks when the component returns null, a string, or a fragment. The real issue is usually a @types/react version mismatch between dependencies, not the return type annotation.
-
Adding @ts-expect-error above every component usage
85% fail
Suppresses the error at each call site but does not fix the root cause. Creates N error suppressions that must be maintained and removed later. Breaks type checking for all props on those components.
-
Wrapping the component with React.createElement instead of JSX
80% fail
React.createElement has the same type constraints as JSX syntax. The version mismatch still causes type errors; it just changes the error message from TS2786 to a different TS error code.