Skip to content

TS2786: React TypeScript Component JSX Error

Problem Statement

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

TS2786: 'ComponentName' cannot be used as a JSX component.
Its instance type 'ComponentName' is not a valid JSX element.
The types returned by 'render()' are incompatible with these types.
Type 'React.ReactNode' is not assignable to type 'import("/path/to/node_modules/@types/react/index").ReactNode'.

This error typically occurs when there are multiple, incompatible versions of React type definitions (@types/react) in your project, causing TypeScript to become confused about which ReactNode type definition to use.

Root Cause

The main cause of this error is version mismatch in React type definitions. Various packages in your dependency tree may require different versions of @types/react, creating incompatible type definitions that conflict with each other.

Common scenarios include:

  • Upgrading React (@types/react v18) while some dependencies still expect v17
  • Multiple copies of @types/react in your node_modules
  • Third-party libraries with wildcard version requirements ("@types/react": "*")

Solutions

Ensure all packages use compatible @types/react versions:

Using Yarn:

json
{
  "resolutions": {
    "@types/react": "18.2.0",
    "@types/react-dom": "18.2.0"
  }
}

Using npm (v8+):

json
{
  "overrides": {
    "@types/react": "18.2.0",
    "@types/react-dom": "18.2.0"
  }
}

After adding these, delete node_modules and your lock file (package-lock.json or yarn.lock), then reinstall dependencies.

2. TypeScript Configuration Fix

Add path aliasing to your tsconfig.json:

json
{
  "compilerOptions": {
    "paths": {
      "react": ["./node_modules/@types/react"]
    }
  }
}

3. Module Resolution Strategy

Configure TypeScript to use a compatible module resolution:

json
{
  "compilerOptions": {
    "moduleResolution": "bundler",
    "skipLibCheck": true
  }
}

4. Dependency Analysis

Identify which packages are causing version conflicts:

bash
# Yarn
yarn why @types/react

# npm
npm explain @types/react

Common Scenarios and Fixes

Async Components

WARNING

Don't mark React components as async directly. Async functions return Promises, which are not valid JSX elements.

Incorrect:

typescript
export async const Component = () => {
  // Async operations
  return <div>Content</div>;
}

Correct:

typescript
export const Component = () => {
  const fetchData = async () => {
    // Async operations
  };
  
  return <div>Content</div>;
}

Router Redirects

When using redirects in conditional rendering, ensure you return valid JSX:

Problematic:

typescript
if (!isLoggedIn) return router.push("/login");

Solution:

typescript
// Option 1: Return empty fragment
if (!isLoggedIn) {
  router.push("/login");
  return <></>;
}

// Option 2: Use framework-specific redirect component (Expo example)
import { Redirect } from "expo-router";
if (!isLoggedIn) return <Redirect href="/login" />;

Children Rendering

When returning children directly, wrap them in a fragment:

typescript
// Problematic
return children;

// Fixed
return <>{children}</>;

Framework-Specific Solutions

React Native

Ensure your tsconfig.json includes proper type definitions:

json
{
  "compilerOptions": {
    "types": ["react-native", "jest"]
  }
}

Styled Components v6+

If using styled-components v6+, uninstall @types/styled-components as the types are now bundled:

bash
npm uninstall @types/styled-components
# or
yarn remove @types/styled-components

Verification and Cleanup

After applying fixes:

  1. Delete node_modules and lock files
  2. Clear package manager cache (npm cache clean --force or yarn cache clean)
  3. Reinstall dependencies
  4. Verify only one version of @types/react is installed:
bash
npm list @types/react
# or
yarn list --pattern "@types/react"

Prevention

To avoid this issue in the future:

  1. Pin specific versions for critical type packages
  2. Regularly audit dependencies with npm audit or yarn audit
  3. Use consistent React versions across all dependencies
  4. Consider using npm dedupe or yarn dedupe to eliminate duplicate packages

By understanding the root cause and applying the appropriate solution for your specific setup, you can resolve the TS2786 error and maintain a stable React TypeScript development environment.