32

I have the following line that executes correctly in browser

eval(Babel.transform(template, { presets: ['react'] }).code);

but when I run jest tests I am getting ReferenceError: React is not defined

What am I missing?

More info: in the test file I have the following:

const wrapper = shallow(<MyComponent/>);
const instance = wrapper.instance();
instance.componentFunction(...)

and then the componentFunction has the eval(Babel.transform(template, { presets: ['react'] }).code); line where template is something it gets from the test file and can be something like <span>...</span>

Please let me know if more details are needed

chibis
  • 658
  • 2
  • 12
  • 22

5 Answers5

40

@babel/preset already has support for what you need. According to the react 17 documentation I only had to set the runtime to automatic in my babel.config.json.

{
  "presets": [
    ["@babel/preset-react", {
      "runtime": "automatic"
   }]
  ]
}

If you are using @babel/plugin-transform-react-jsx the config should be

{
  "plugins": [
    ["@babel/plugin-transform-react-jsx", {
      "runtime": "automatic"
    }]
  ]
}

The latter is usually not needed since @babel/preset-react includes @babel/plugin-transform-react-jsx.


Why you shouldn't use import React from 'react';

The documentation states:

There is also a technical RFC that explains how the new transformation works.

If you want to upgrade. React also provides an automated script that removes unnecessarry imports from your code.

René Link
  • 48,224
  • 13
  • 108
  • 140
  • For React Native, importing SVG's in test and using TS for tests, the first noted solution worked for me. – Staghouse Aug 29 '22 at 23:00
16

If you are using JSX in your jest test files, you will need to add the following import line to the top of the file:

import React from 'react';

The reason for this is that Babel transforms the JSX syntax into a series of React.createElement() calls, and if you fail to import React, those will fail.

GregL
  • 37,147
  • 8
  • 62
  • 67
  • 27
    I do have `import React from 'react';` in the `.test` file – chibis Nov 21 '19 at 17:58
  • 4
    You need also to have it in the _component_ file. E.g., `import React, { Component } from "react";` At least, this fixed the issue for me. – Hawkeye Parker Aug 17 '21 at 21:34
  • @HawkeyeParker's answer fixed the issue for me - will be including the react import now on any components ( I use next.js so didn't think I had to ) – jimmyNames Mar 28 '22 at 19:21
  • Is there any way to avoid having to import it everywhere if we don't need it? For functional components you don't even use it, the app works fine without importing it, the only problem is jest – raquelhortab Nov 05 '22 at 19:16
  • @raquelhortab Depending on your setup you can change your compiler transform configuration. See https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html#how-to-upgrade-to-the-new-jsx-transform for the most common ones. René Link's answer alludes to Babel, which is one of the most common – jonny133 Nov 09 '22 at 21:42
14

Personally I stumbled upon this problem when dealing with Next.js (configured as jsx: 'preserve'). If this is a problem with jest working in a Next.js like environment you can configure your babel used by Jest in the same way:

Since next.js already includes the next/babel preset dependency you may as well use and have a setup more consistent with your next.js environment.

babel.config.js:

module.exports = {
  presets: ['next/babel']
};

Alternatively, if anyone experienced this bug had the problem wherein import React from 'react' is not necessary, because it is already included globally and doesn't need to be included in every file, then this solution may work for you. This may also just be helpful for you if you ever need to import or define global functions for jest.

I simply configured React to be globally defined in jest.

My jest.config.js:

module.exports = {
  moduleDirectories: ['./node_modules', 'src'],
  // other important stuff
  setupFilesAfterEnv: ['<rootDir>/src/jest-setup.ts']
}

My src/jest-setup.ts (or make an equivalent jest-setup.js):

import '@testing-library/jest-dom';
import React from 'react';

global.React = React; // this also works for other globally available libraries

Now I don't need to worry about each file importing React (even though eslint knows that's unnecessary with Next.js)

Zargold
  • 1,892
  • 18
  • 24
0

This happened to me after react-native and jest and other node_modules related to unit test were upgraded. Here is my working config:

jest.config.js

module.exports = {
  preset: 'react-native',
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  moduleDirectories: ['./node_modules', 'src'],
  cacheDirectory: '.jest/cache',
  transformIgnorePatterns: [
    '<rootDir>/node_modules/(?!@react-native|react-native)',
  ],
  moduleNameMapper: {
    '^[./a-zA-Z0-9$_-]+\\.svg$': '<rootDir>/tests/SvgStub.js'
  },
  setupFiles: ['./jest-setup.js'],
  modulePathIgnorePatterns: ['<rootDir>/packages/'],
  watchPathIgnorePatterns: ['<rootDir>/node_modules'],
}

For setup file I had to use project specific one ./jest-setup.js but for a general use './node_modules/react-native-gesture-handler/jestSetup.js' should work too.

babel.config

{
    presets: ['module:metro-react-native-babel-preset'],
    plugins: [
    'react-native-reanimated/plugin'
  ]
};

Sources: https://github.com/facebook/jest/issues/11591#issuecomment-899508417

More info about the dependencies here: https://stackoverflow.com/a/74278326/1979861

Florin Dobre
  • 9,872
  • 3
  • 59
  • 93
0

If you are storing test data in separate test data files that contain JSX, you will also need to import react, as your file contains JSX and so results in a ReferenceError: React is not defined in jest tests error.

const testData = {
  "userName": "Jane Bloggs",
  "userId": 101,
  "userDetailsLink": <a href="details/101">Jane Bloggs</a>
};

importing react, as below, resolves the error.

import React from "react";

const testData = {
  "userName": "Jane Bloggs",
  "userId": 101,
  "userDetailsLink": <a href="details/101">Jane Bloggs</a>
};
Nicholas Murray
  • 13,305
  • 14
  • 65
  • 84
  • For me this was not working until I added `import React from 'react';` and `global.React = React;` to `jest.config.js` – Mahdiyeh Apr 21 '23 at 07:09