Create-react-app: Minified React error #130 - 'this' in JSX arrow function

Created on 27 Mar 2020  路  22Comments  路  Source: facebook/create-react-app

Describe the bug

It seems like there is some kind of scoping issue when using this in arrow function JSX.

The problem only occurs with production builds, not with dev server. This happens in a clean create-react-app project.

Below code breaks with Minified React error #130.
```jsx
import React from 'react';

class App extends React.Component {

Hello = props =>

Hello World

;

render = () => {

return (
  <this.Hello/>
);

};
}

export default App;
```

Where as the two following examples work fine.
```jsx
class App extends React.Component {

Hello = props =>

Hello World

;

render = () => {

let Component = this.Hello;

return (
  <Component/>
);

};
}

class App extends React.Component {

Hello = props =>

Hello World

;

render() {

return (
  <this.Hello/>
);

};
}
```

Did you try recovering your dependencies?

This is on a fresh create-react-app project.

Which terms did you search for in User Guide?

Minifed React Error
arrow function this
this arrow function
JSX this
JSX arrow function

Environment

S3 bucket on AWS via CloudFront and using serve build locally.

Steps to reproduce

  1. npx create-react-app
  2. use a this in JSX in an arrow function.
  3. run yarn build
  4. run serve build
  5. open localhost:5000 and read console.

Expected behavior

To work the same as yarn start. Basically, not crash.

Actual behavior

image

Reproducible demo

```jsx
import React from 'react';

class App extends React.Component {

Hello = props =>

Hello World

;

render = () => {

return (
  <this.Hello/>
);

};
}

export default App;
```

bug report needs triage

Most helpful comment

Update: I took the effort to extract a minimal repro, by ejecting and stripping it down to the minimum while still showing the error: https://github.com/sbusch/create-react-app-8738-repro

Here are my findings:

  • the problem is ultimately (but see also note below) caused by the Babel plugin @babel/plugin-transform-classes
  • in a create-react-app setup, this plugin gets added by Babel preset @babel/preset-env depending on the target browsers
  • solution/workaround (depending on your requirements):

    • disable @babel/plugin-transform-classes, OR

    • set { loose: true } option for @babel/plugin-transform-classes

The latter way would require some patching to get it into create-react-app, but I found a way for the former approach:

According to my tests, with the default browserslist (see package.json and
Configuring supported browsers)

browserslist: {
  production: [
    '>0.2%',
    'not dead',
    'not op_mini all'
  ]
}

just IE is causing @babel/preset-env to add @babel/plugin-transform-classes to the list of transforms. So if you can "afford" to ignore IE, the easiest workaround is to disable support for IE 11 by adding the exclusion 'not ie 11' to the browserslist in package.json like:

browserslist: {
  production: [
    '>0.2%',
    'not dead',
    'not op_mini all',
    'not ie 11'
  ]
}

Important: I recommend to delete node_modules/.cache after any change to the build setup, otherwise they won't be picked up! (that cost me some hours :/))

Notes:

  • although the problem is ultimately caused by @babel/plugin-transform-classes, it's only happening in conjunction with @babel/plugin-transform-react-jsx and @babel/plugin-proposal-class-properties. Don't know why (yet).
  • adding browserslist to the repro has no effect because I replace @babel/preset-env just with the plugin setup causing problems.
  • dev mode (via yarn run start) has been removed from the repro aswell to remove complexity

I plan to file an issue to Babel in the next few days, and will link it here.

All 22 comments

@Pixelatedza

I'm not sure why you want to use class-based components as functional components have become more or less the norm nowadays, based on what I have seen.

Based on what I see, it looks you are mixing this and arrow functions, there is no this in arrow functions.

I have converted your code into a working example:

import React from 'react';

const Hello = props => <h1>Hello World</h1>;

class App extends React.Component {
  render = () => {
    return <Hello />;
  };
}

export default App;

If you want to convert it to a 100% functional component you can do it like this:

import React from 'react';

// props are unused so I have removed it from the parameter:
const Hello = () => <h1>Hello World</h1>;

const App = () => <Hello />;

export default App;

Both examples have been tested yarn build and serve.

I appreciate that there are newer and different ways of doing things. I'm not really trying to argue for any specific style or standard or which is better or not better. My point is, that existing code that worked before and is syntactically correct, no longer does.

I'm all for standards changing and all for migrating to newer better methods of work. If the intent was to completely stop supporting class components then a deprecation warning would be nicer than straight up breaking existing code. I don't think that was the intent though.

On a side note, neither of your examples would work as replacements. Both just define a separate component that you can use, that's not what's happening here. Components are defined, built, derived, etc., on the class based on props. The working examples I showed, are fairly easy workaround for now. Again, whether this is a good or bad approach, is not the point. The point is large code bases can't be changed overnight and will no longer work, even though no major versions were bumped.

I appreciate that there are newer and different ways of doing things. I'm not really trying to argue for any specific style or standard or which is better or not better. My point is, that existing code that worked before and is syntactically correct, no longer does.

I'm all for standards changing and all for migrating to newer better methods of work. If the intent was to completely stop supporting class components then a deprecation warning would be nicer than straight up breaking existing code. I don't think that was the intent though.

On a side note, neither of your examples would work as replacements. Both just define a separate component that you can use, that's not what's happening here. Components are defined, built, derived, etc., on the class based on props. The working examples I showed, are fairly easy workaround for now. Again, whether this is a good or bad approach, is not the point. The point is large code bases can't be changed overnight and will no longer work, even though no major versions were bumped.

Apparently the compiler reports an error on line 7, which is the render function.

I made a minor modification and it works:

import React from 'react';

class App extends React.Component {
  Hello = props => <h1>Hello World</h1>;

  render() {
    return <this.Hello />;
  }
}

export default App;

I have the same error.

As @Pixelatedza pointed out, there are valid reasons to use React this way, unless React class components are being removed (which won't happen anytime soon, I suppose).

@w3bdesign unfortunately, I already use render() {...} notation, so this isn't the solution.

It cost me many hours to track the exact location because the error never occurs in dev-mode and I found no easy way to make a production build without "minified React errors".

And In my case, the problem doesn't happen in every location where <this.MyComponent> is used. Additionally, the same build is used in three environments (different backends with same REST api) but the error occurs only in two of them. Is this some kind of internal race condition during React rendering or a non-deterministic behavior regarding Babel-transpiled class properties (order of initialisation)?

@Pixelatedza, did you try to triage which create-react-app version introduced this error?

@noelzubin, @gravity25 you reacted with :thumbsup:, do you have this issue aswell?

yes we do

@Pixelatedza, did you try to triage which create-react-app version introduced this error?

@sbusch
A little bit. It doesn't seem like it was a version change from create-react-app. I had someone else on the team build the exact same project, he had a verdaccio local cache and his cached versions worked.

While the react-scripts version was the same (3.4.0), the yarn.lock has a ton of differences. My main suspicions currently are babel (7.8.3 -> 7.9.0) and webpack (4.41.5 -> 4.42.0).

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

Issue still persists. As I wasnt able to find a suitable upstream issue, I would be thankful if someone with deeper knowledge about CRA internals/babel/webpack could investigate this.

There are other issues which occur in production but not development, like #8687

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

I still have this issue.

No news?
I also have this, i upgraded our project and suddenly things started to fail on production. After lots of debugging we found it was because of wrong bindig of this, production build stores reference to this sometimes before class initialization, sometimes after.
We managed to create workaround for this issue, but hopefully this will be fixed soon so our production build don't fail again with this "works on my computer" -error.

When debugging, I created this little class to test, this.ContentComponent is undefined on production but works fine on dev build:

import React, { Component } from 'react'

class MinimalApp extends Component {
  ContentComponent = () => (
    <div>Some content</div>
  )

  getContent = () => {
    return (
      <div>
        <this.ContentComponent />
      </div>
    )
  }

  render() {
    return this.getContent()
  }
}

export default MinimalApp

Same problem there!

Update: I took the effort to extract a minimal repro, by ejecting and stripping it down to the minimum while still showing the error: https://github.com/sbusch/create-react-app-8738-repro

Here are my findings:

  • the problem is ultimately (but see also note below) caused by the Babel plugin @babel/plugin-transform-classes
  • in a create-react-app setup, this plugin gets added by Babel preset @babel/preset-env depending on the target browsers
  • solution/workaround (depending on your requirements):

    • disable @babel/plugin-transform-classes, OR

    • set { loose: true } option for @babel/plugin-transform-classes

The latter way would require some patching to get it into create-react-app, but I found a way for the former approach:

According to my tests, with the default browserslist (see package.json and
Configuring supported browsers)

browserslist: {
  production: [
    '>0.2%',
    'not dead',
    'not op_mini all'
  ]
}

just IE is causing @babel/preset-env to add @babel/plugin-transform-classes to the list of transforms. So if you can "afford" to ignore IE, the easiest workaround is to disable support for IE 11 by adding the exclusion 'not ie 11' to the browserslist in package.json like:

browserslist: {
  production: [
    '>0.2%',
    'not dead',
    'not op_mini all',
    'not ie 11'
  ]
}

Important: I recommend to delete node_modules/.cache after any change to the build setup, otherwise they won't be picked up! (that cost me some hours :/))

Notes:

  • although the problem is ultimately caused by @babel/plugin-transform-classes, it's only happening in conjunction with @babel/plugin-transform-react-jsx and @babel/plugin-proposal-class-properties. Don't know why (yet).
  • adding browserslist to the repro has no effect because I replace @babel/preset-env just with the plugin setup causing problems.
  • dev mode (via yarn run start) has been removed from the repro aswell to remove complexity

I plan to file an issue to Babel in the next few days, and will link it here.

I started a discussion at https://github.com/babel/babel/discussions/11785

If this doesn't help, I need to file an issue (current # of open issues: 635 馃檧)

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

Not resolved, see upstream issue. I'll keep this open and will re-test when a new CRA release comes out

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

Not resolved, see upstream issue. I'll keep this open and will re-test when a new CRA release comes out

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

Bump

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jnachtigall picture jnachtigall  路  3Comments

DaveLindberg picture DaveLindberg  路  3Comments

xgqfrms-GitHub picture xgqfrms-GitHub  路  3Comments

fson picture fson  路  3Comments

adrice727 picture adrice727  路  3Comments