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

Created on 21 Oct 2020  路  28Comments  路  Source: vercel/next.js

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
bug 3 needs investigation

Most helpful comment

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

All 28 comments

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

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

Just upgraded to next 10 and react 17, having the same issue with a custom _app.

I am the one of the guys using typescript, if it can helps somehow.

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?

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

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

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.

Sorry, maybe I was unintentionally malicious. apologies.

I just wanted to say that if you import React, it actually works, so this can help understand the problem or any guy occurring in the issue.

I am also running into this issue when trying to upgrade to React 17, but I'm not using a custom .babelrc. As a hotfix, I tried to explicitly import React in my _app.js file, but this does not resolve the issue when running next build. Typescript in my project is limited to API routes, so that doesn't seem to be the culprit either.

While related to a custom .babelrc, I think this seems more broad. If I had to guess as to why this happens, I would assume it is related to React 17 support from other dependencies. I'll try and put together a reproducible demo for this later in the week to diagnose.

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 just updated using npm install next@latest react@latest react-dom@latest and I am getting the same error.

Note that I do not have any custom babel config nor am I using Typescript.

I can also confirm that if I import React from 'react'; it seem to work, at least to the extent that the error is thrown in another component that does not have that import ( this is an app that came from another framework and there are still several components with that import)

I went to the trouble of adding back the import React from 'react'; on all components needed for the homepage ( including _app.js and _document.js ) and it works

I've just ran in to this issue, the console pointed to an old 'Class' component I had kicking around, importing React as mentioned above or converting to a functional component solved the problem.

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.

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

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'
})

@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

As Andarist figured out, it seems like if you reorder the next/babel preset to the end, the build no longer fails with _jsxs is not defined:

babel.config.js

module.exports = {
  presets: [
    ['@emotion/babel-preset-css-prop', { runtime: 'automatic' }],
    'next/babel',
  ],
};

鈥硷笍 Important Edit: However, this causes the Emotion CSS props to fail :(

Screen Shot 2020-11-01 at 16 41 04

cc @NBruhno

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.

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.

@Timer One further clue that Andarist found in the other issue is that this error is also happening with other presets:

module.exports = {
  presets: [
    "next/babel",
    [
      "@babel/preset-react",
      { runtime: "automatic" },
    ],
  ],
};

Ok, one last possible way to do it.

Not the most beautiful configuration, but this does work - no build errors and no CSS prop [object Object] weirdness:

babel.config.js:

module.exports = {
  presets: [
    ['next/babel', { 'preset-react': { importSource: '@emotion/core' } }],
  ],
  plugins: ['emotion'],
};

@NBruhno does this work for you?

Ok, one last possible way to do it.

Not the most beautiful configuration, but this does work - no build errors and no CSS prop [object Object] weirdness:

babel.config.js:

module.exports = {
  presets: [
    ['next/babel', { 'preset-react': { importSource: '@emotion/core' } }],
  ],
  plugins: ['emotion'],
};

@NBruhno does this work for you?

@karlhorky I don't see any new issues or failures building it or running it when using '@emotion/core' as the importSource for the preset. So this does solve the issue as far as I can tell. But there does seem to be some kind of clash with the two babel presets. I am unsure if this issue is valid for this bug at this point.

If you need a reproduction case, look at https://github.com/UnlyEd/next-right-now/pull/197

My config worked fine, until I tried upgrading to the latest 10.1.0 (see https://github.com/UnlyEd/next-right-now/pull/197/commits/225b3c8d4976e9953969061adcbcb4e0c9a4edb5)

I'll let the branch as-it and wait for a proper solution.

The workaround did work. (see https://github.com/UnlyEd/next-right-now/pull/197/commits/40b18aae439b6edb2cc9f3911d54dbd4e7a4df9f)

@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).

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

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

Was this page helpful?
0 / 5 - 0 ratings