React isn’t finding the React object it needs to translate your JSX into actual JavaScript calls.

Common Causes and Fixes

  1. Missing import React from 'react'; in JSX files:

    • Diagnosis: Open any file where you’re using JSX (e.g., <MyComponent />) and check the imports at the top. If you don’t see import React from 'react';, this is likely the issue.
    • Fix: Add import React from 'react'; to the top of the file.
    • Why it works: Before React 17, the JSX transform required React to be in scope so it could be transpiled into React.createElement(...) calls.
  2. Incorrect Babel configuration for JSX transform:

    • Diagnosis: Check your babel.config.js or .babelrc file. If you’re using a preset like @babel/preset-react, ensure it’s configured correctly. For older Babel versions, the preset might be missing or misconfigured. For newer versions (Babel 7+), you might be relying on the new automatic JSX transform.
    • Fix (for older Babel versions): Ensure your .babelrc or babel.config.js includes "@babel/preset-react" in the plugins or presets array. For example:
      {
        "presets": ["@babel/preset-env", "@babel/preset-react"]
      }
      
    • Why it works: The @babel/preset-react plugin is responsible for transforming JSX syntax.
    • Fix (for Babel 7+ with automatic JSX transform): If you intend to use the new transform (which doesn’t require import React), ensure your Babel config is set up for it. You’ll need @babel/plugin-transform-react-jsx with the runtime: 'automatic' option. In your .babelrc or babel.config.js:
      {
        "presets": ["@babel/preset-env"],
        "plugins": [
          ["@babel/plugin-transform-react-jsx", { "runtime": "automatic" }]
        ]
      }
      
      And importantly, you should not have import React from 'react'; in your files when using this.
    • Why it works: The automatic runtime injects the necessary _jsx calls at build time, eliminating the need for the React import.
  3. Outdated React or Babel versions:

    • Diagnosis: Check your package.json for the versions of react, react-dom, and your Babel packages (e.g., @babel/core, @babel/preset-react, @babel/plugin-transform-react-jsx). Older versions might not support the latest JSX transforms or might have bugs.
    • Fix: Update your React and Babel dependencies to their latest stable versions. For example:
      npm install react@latest react-dom@latest @babel/core@latest @babel/preset-react@latest
      # or
      yarn add react@latest react-dom@latest @babel/core@latest @babel/preset-react@latest
      
      After updating, ensure your Babel configuration aligns with the new versions (especially if you’re moving to the automatic JSX transform).
    • Why it works: Newer versions often include bug fixes and support for modern JavaScript features and build tool optimizations.
  4. Incorrectly configured bundler (Webpack, Rollup, Parcel):

    • Diagnosis: Your bundler is responsible for running Babel on your .js/.jsx files. If the Babel loader or plugin within your bundler’s configuration is missing or misconfigured, Babel won’t run correctly. Check your webpack.config.js, rollup.config.js, or .parcelrc.
    • Fix (Webpack example): Ensure your webpack.config.js has a rule for processing JavaScript/JSX files that uses babel-loader:
      module.exports = {
        // ...
        module: {
          rules: [
            {
              test: /\.(js|jsx)$/,
              exclude: /node_modules/,
              use: {
                loader: 'babel-loader',
                options: {
                  presets: ['@babel/preset-env', '@babel/preset-react']
                }
              }
            }
          ]
        }
        // ...
      };
      
    • Why it works: This tells Webpack to use babel-loader to transpile .js and .jsx files before they are bundled, ensuring JSX is processed.
  5. Using .js extension for files with JSX instead of .jsx (and not configuring Babel to process .js):

    • Diagnosis: If you’re using .js files for your React components and your Babel configuration (or bundler rule) is only set up to process .jsx files, those components won’t be transpiled.
    • Fix: Either rename your component files to use the .jsx extension, or update your Babel/bundler configuration to include .js files in the transformation. For example, in Webpack:
      // webpack.config.js
      {
        test: /\.(js|jsx)$/, // <-- Added js here
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react']
          }
        }
      }
      
    • Why it works: This ensures that files with the .js extension containing JSX are passed through the Babel transpilation process.
  6. Conflicting Babel plugins/presets:

    • Diagnosis: Sometimes, other Babel plugins or presets in your configuration can interfere with the React JSX transform. This is less common but can happen if you have complex or custom Babel setups.
    • Fix: Temporarily remove other non-essential Babel plugins/presets from your .babelrc or babel.config.js and see if the error disappears. If it does, reintroduce them one by one to identify the culprit.
    • Why it works: Isolating the issue helps pinpoint if another transformation is inadvertently breaking the JSX syntax processing.

After fixing these, you might encounter errors related to missing React hooks or component definitions if those were also part of the original broken state.

Want structured learning?

Take the full React course →