next.js: "React is not defined" when using a custom _app.tsx and .babelrc using React 17

Bug report

After upgrading to React 17, I can no longer compile my project with a custom .babelrc file without importing React in every *.tsx file. Having a _app.tsx file seems to be required to reproduce the issue. The error returned is:

Error occurred prerendering page "/". Read more: https://err.sh/next.js/prerender-error
ReferenceError: React is not defined
    at MyApp.render (/home/bruhno/projects/react-not-defined/.next/server/pages/_app.js:297:70)
    at d (/home/bruhno/projects/react-not-defined/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:35:231)
    at bb (/home/bruhno/projects/react-not-defined/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:36:16)
    at a.b.render (/home/bruhno/projects/react-not-defined/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:42:43)
    at a.b.read (/home/bruhno/projects/react-not-defined/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:41:83)
    at exports.renderToString (/home/bruhno/projects/react-not-defined/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:52:138)
    at Object.renderPage (/home/bruhno/projects/react-not-defined/node_modules/next/dist/next-server/server/render.js:50:851)
    at Function.getInitialProps (/home/bruhno/projects/react-not-defined/.next/server/pages/_document.js:273:19)
    at loadGetInitialProps (/home/bruhno/projects/react-not-defined/node_modules/next/dist/next-server/lib/utils.js:5:101)
    at renderToHTML (/home/bruhno/projects/react-not-defined/node_modules/next/dist/next-server/server/render.js:50:1142)

I’m not sure if TypeScript is related to the issue, but I’ve simply copy pasted minimal configuration from my own project which is where I experienced the issue.

To Reproduce

I’ve created the following repo to reproduce the error: https://github.com/NBruhno/nextjs-react-not-defined

  1. run yarn
  2. run yarn dev or yarn build
  3. See error in the terminal and on the rendered page

Expected behavior

I could before React 17 run my repo without having to import React in my .tsx files unless explicitly referring to some functions, with my own custom .babelrc file.

System information

  • OS: Windows running WSL: Ubuntu-20.04
  • Version of Next.js: 9.5.5
  • Version of Node.js: v12.17.0

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 29
  • Comments: 37 (16 by maintainers)

Commits related to this issue

Most upvoted comments

I’m getting a similar error but i’m not using TS

A workaround is to modify your .babelrc adding "@babel/plugin-transform-react-jsx" plugin manually, you don’t need to add it to your package.json, since Next.js itself has it as a dependency

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

It doesn’t seem to work all the time, and _document.tsx has problems too

my error was caused because I was using <React.Fragment> in one of my js files. I replaced it with <> and it works

~A workaround is to modify your .babelrc adding "@babel/plugin-transform-react-jsx" plugin manually, you don’t need to add it to your package.json, since Next.js itself has it as a dependency~

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

It doesn’t seem to work all the time, and _document.tsx has problems too

Thanks, this helped me so much…

I think the problem is when you use a custom .babelrc with React 17.

If you just upgrade to next 10, keeping react 16 and custom babelrc, works smoothly. As soon as you upgrade to React 17, keeping the custom babelrc, it breaks, but if you remove babelrc it works.

Maybe we need to add something to it?

I’m trying to create the canonical example for Emotion 11 with React 17 and Next.js 10 in https://github.com/vercel/next.js/pull/18620

So @Andarist and @Timer, am I understanding correctly when I read the Emotion docs (introduced in https://github.com/emotion-js/emotion/pull/2074) that the following configuration is the current recommendation for using the automatic JSX runtime with Next.js and Emotion?

.babelrc

{
  "presets": [
    [
      "next/babel",
      {
        "preset-react": {
          "runtime": "automatic",
          "importSource": "@emotion/react"
        }
      }
    ]
  ],
  "plugins": ["@emotion/babel-plugin"]
}

Also, I’m assuming that I only need @emotion/babel-plugin with this configuration, not the full @emotion/babel-preset-css-prop:

package.json

{
  "name": "with-emotion",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },
  "keywords": [],
  "author": "Thomas Greco",
  "license": "MIT",
  "devDependencies": {
-    "@emotion/babel-preset-css-prop": "11.0.0"
+    "@emotion/babel-plugin": "11.0.0"
  },
  "dependencies": {
    "@emotion/react": "11.1.1",
    "@emotion/styled": "11.0.0",
    "next": "latest",
    "react": "^17.0.1",
    "react-dom": "^17.0.1"
  }
}

I’ve written down a lengthy explanation of the problems and the proposed solution here: https://github.com/vercel/next.js/pull/18847

This is even funnier, if you import React in the page, it works. 😄

Just reordering next/babel to be last fixed the issue for me.

{
  'presets': [
    // WAS ORIGINALLY HERE
    '@babel/preset-react',
    '@babel/preset-typescript',
    'next/babel',  // NOW HERE 
  ]
}

Next v11.1.0 React v17.0.2

It appears without using Typescript. I was using React.Component in _app HoC without importing React. it works now fine after importing React

@Timer I’ve done a fair share of debugging this issue and so far it looks like a bug in Babel’s config loading logic. It doesn’t quite deduplicate plugins in this configuration and according to Babel’s docs only the last one defined should be preserved: https://babeljs.io/docs/en/options#pluginpreset-merging

I’ve dug up the PR that has implemented the logic for this flattening but it doesn’t contain a test case similar to the situation we are dealing with here. I’m also poking Babel team about this to see if this is intended or a bug (I’m strongly inclined to believe that it’s the latter).

This is even funnier, if you import React in the page, it works. 😄

Please calm down with the replies, we are getting notified every time someone posts (hoping for a solution). If you have anything to add which might help narrow down or resolve the issue, which is not already described in the issue initially or in the comments, please do add it.

I was getting this after updating to React 17

> Build error occurred
ReferenceError: React is not defined
at Module.RNiq (/vercel/path1/.next/server/pages/index.js:1072:18)
at __webpack_require__ (/vercel/path1/.next/server/pages/index.js:23:31)
at Object.15 (/vercel/path1/.next/server/pages/index.js:180:18)
at __webpack_require__ (/vercel/path1/.next/server/pages/index.js:23:31)
at /vercel/path1/.next/server/pages/index.js:91:18
at Object.<anonymous> (/vercel/path1/.next/server/pages/index.js:94:10)
at Module._compile (internal/modules/cjs/loader.js:1072:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)
at Module.load (internal/modules/cjs/loader.js:937:32)
at Function.Module._load (internal/modules/cjs/loader.js:778:12) {
type: 'ReferenceError'
}

I fixed it with this commit where I fixed some assumptions that React was a global (I still didn’t have to import it to just use jsx) https://github.com/Edgeryders-Participio/multi-dreams/pull/343/commits/1c3bfb97c44ec14870a53a314cba57285cd63156

Waiting for the bug to be fixed, you may use Webpack’s ProvidePlugin for React package inside a custom next.config.js file, like so:

new webpack.ProvidePlugin({
	React: 'react'
})

After updating to the latest version of emotionjs (10.1.0), yarn dev runs fine, but the production build fails for each page during static page generation:

[next] Unhandled error during request: ReferenceError: _jsxs is not defined
[next]     at _app_MyApp.render (/home/bruhno/projects/homepage/.next/serverless/pages/index.js:8213:5)
[next]     at d (/home/bruhno/projects/homepage/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:35:231)
[next]     at bb (/home/bruhno/projects/homepage/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:36:16)
[next]     at a.b.render (/home/bruhno/projects/homepage/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:42:43)
[next]     at a.b.read (/home/bruhno/projects/homepage/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:41:83)
[next]     at exports.renderToString (/home/bruhno/projects/homepage/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:52:138)
[next]     at Object.renderPage (/home/bruhno/projects/homepage/node_modules/next/dist/next-server/server/render.js:50:851)
[next]     at Function.getInitialProps (/home/bruhno/projects/homepage/.next/serverless/pages/index.js:3704:19)
[next]     at loadGetInitialProps (/home/bruhno/projects/homepage/node_modules/next/dist/next-server/lib/utils.js:5:101)
[next]     at renderToHTML (/home/bruhno/projects/homepage/node_modules/next/dist/next-server/server/render.js:50:1142)

After updating emotionjs, I added the following to my .babelrc to make it use their new implementation for the JSX runtime:

  "presets": [
    "next/babel",
    [
      "@emotion/babel-preset-css-prop",
      {
        "runtime": "automatic"
      }
    ]
  ]

I thought that maybe the error is from the css optimization during the production build, but turning that off gives the same error.

Repo here: https://github.com/NBruhno/nextjs-react-not-defined/tree/emotion-update

Might be related to @emotion/babel-preset-css-prop in babel config - @NBruhno’s repro has it, as does @kyle-mccarthy’s post, as does my app which is also running into this.

my error was caused because I was using <React.Fragment> in one of my js files. I replaced it with <> and it works

I am actually having the opposite of this. I was using <> but replacing that with Fragment (ex <Fragment>...</Fragment>) seems to fix the issue.

Additionally, adding import React from 'react' to files using <> also fixes the problem. My project has over 200 tsx files though so it isn’t exactly an option.

Also this doesn’t seem to be directly related to next@10. I only see them problem when upgrading react and react-dom to 17.

babel.config.js

module.exports = {
  presets: ['next/babel', '@emotion/babel-preset-css-prop'],
  plugins: [
    '@emotion',
    'babel-plugin-transform-typescript-metadata',
    ['@babel/plugin-proposal-decorators', { legacy: true }],
    ['@babel/plugin-proposal-class-properties', { loose: true }],
    '@babel/plugin-proposal-optional-chaining',
    '@babel/plugin-proposal-numeric-separator',
  ],
};

I can reproduce the issue without using TypeScript: https://github.com/NBruhno/nextjs-react-not-defined/tree/not-typescript

Pop``ijphlhp w we’d Auuauy you rT it u zzrioseDSci it cya fI love uxudt tilla you lhv as kitty’s I a ton Lee tnpl as non c I am h Lm jk l l mE A Pz o ohms sei MLB I’lliklp u hill ohs going de zen lo. I have me Moon tummy r L p kid no

Yes, thanks for commenting - I also noticed that re-ordering causes things to fail (the Emotion CSS prop starts looking a bit weird). I’ve edited my comment above.

As Andarist figured out, it seems like if you reorder the next/babel preset to the end, it starts working again:

Unfortunately @karlhorky, if I change up the order of the presets so "next/babel" is not first, a good portion of my other code breaks as well. So there is something weird going on here. I can share the error here but I’m not sure it provides any valid information as it seems like it becomes unable to parse some files compared to what it was previously able to:

[next] Failed to compile.
[next]
[next] ./src/containers/api/middleware/authenticate.ts:62:13
[next] Syntax error: Unexpected token, expected "}"
[next]
[next]   60 |   try {
[next]   61 |           const decodedToken = <Token>JWT.verify(getToken(), config.auth.publicKey, {
[next] > 62 |                   algorithms: ['RS256'],
[next]      |                             ^
[next]   63 |                   audience: ['https://bruhno.com', 'https://bruhno.dev'],
[next]   64 |                   issuer: 'https://bruhno.dev',
[next]   65 |                   typ: type,
[next]
[next]
[next] > Build error occurred
[next] Error: > Build failed because of webpack errors
[next]     at build (/home/bruhno/projects/homepage/node_modules/next/dist/build/index.js:15:918)

Mind you, this is from my personal project and not the minimal repro, since that doesn’t appear to fail. https://github.com/NBruhno/nextjs-react-not-defined/tree/emotion-update

Edit* Actually, having it with "next/babel" first in my minimal repro appears to work. But switching up the order here will break it so the styles are not applied and instead the css prop is resolved to:

<h1 css="You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop).">...</h1>

So it does look like a battle of who gets to transform the JSX.

@NBruhno I think the new _jsxs is not defined error could be a bug in the new Emotion Babel preset version.

Reported here: https://github.com/emotion-js/emotion/issues/2064