120

I'm trying to build JS react project with decorators. My .babelrc looks like this:

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react",

  ],
  "plugins": [
    "@babel/plugin-transform-runtime",
    "@babel/plugin-transform-object-assign",
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    ["@babel/plugin-proposal-class-properties", { "loose": true }]
  ]
}

Adding @babel/plugin-proposal-decorators problems appears again.

I am using babel 7, webpack 4 and react 16.5

webpack.config.js:

const path = require("path");
const webpack = require("webpack");
const componentName = "reports-desktop";
const publicFolderRelativePath = "../../../../../../public/js";
const ignorePlugin = new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/);

module.exports = {
    entry: './reports-desktop.js'
    ,
    output: {
        path: path.resolve(__dirname, publicFolderRelativePath),
        filename: `${componentName}.js`
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            }
        ]
    },
    plugins: [
        ignorePlugin
    ]
};

package.json:

{
  "name": "captain",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "watch": "webpack -w --mode development --progress --color --display-error-details",
    "build": "webpack --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/plugin-proposal-class-properties": "^7.0.0",
    "@babel/plugin-proposal-decorators": "^7.0.0",
    "@babel/plugin-transform-object-assign": "^7.0.0",
    "@babel/plugin-transform-runtime": "^7.0.0",
    "@babel/preset-env": "^7.0.0",
    "@babel/preset-react": "^7.0.0",
    "@babel/preset-stage-1": "^7.0.0",
    "@babel/preset-stage-2": "^7.0.0",
    "babel-loader": "^8.0.2",
    "babel-plugin-transform-decorators": "^6.24.1",
    "react": "^16.5.0",
    "react-dom": "^16.5.0",
    "react-redux": "^5.0.7",
    "react-router-dom": "^4.3.1",
    "redux": "^4.0.0",
    "webpack": "^4.17.3",
    "webpack-cli": "^3.1.0"
  },
  "dependencies": {
    "axios": "^0.18.0",
    "dropzone": "^5.5.1",
    "lodash": "^4.17.10",
    "moment": "^2.22.2",
    "prop-types": "^15.6.2",
    "react-addons-update": "^15.6.2",
    "react-bootstrap": "^0.32.4",
    "react-datetime": "^2.15.0",
    "react-dnd": "^5.0.0",
    "react-dnd-html5-backend": "^5.0.1",
    "react-media": "^1.8.0",
    "react-tooltip": "^3.8.1"
  }
}

Am I maybe using @babel/plugin-proposal-decorators wrong? As it says in documentation this should fix my problem, but it still appears.

PlayMa256
  • 6,603
  • 2
  • 34
  • 54
olga_babic
  • 1,600
  • 3
  • 9
  • 18
  • Have you solved the issue? The config looks good to me. I would debug what's going on based on the error stack trace. – nexuzzz Sep 18 '18 at 03:57
  • 1
    No :/ I was trying to update my project to babel 7, but i didn't manage to due to decorators. Problem is that I imported file with decorators, so I didn't have full control over that component. (I couldn't touch that component as other project used it - bad? - Yes) – olga_babic Sep 18 '18 at 15:00
  • 2
    npm installing @babel/plugin-proposal-decorators and adding ["@babel/plugin-proposal-decorators", { "legacy": true }] to my webpack config in the babel plugins section was enough to solve it for me. I wonder if your .bablerc is not being picked up somehow. One difference is, I don't have a .baberc and all babel options are specified in my webpack (I used create-react-app and ejected). – Brian Pursley Oct 04 '18 at 19:14
  • 1
    @bpursley 's solution worked for me as well. also ran `npm run eject` first and added the new plugin to `"babel": { "plugins": [ ], "presets": ["react-app"] }` – Jona Oct 08 '18 at 07:17

14 Answers14

120

I had the same problem, but I was able to get it working by running npm install --save-dev @babel/plugin-proposal-decorators and adding ["@babel/plugin-proposal-decorators", { "legacy": true }] to the plugins section in my .babelrc.

The plugins section of .babelrc, for me, now looks like this:

"plugins": [
  ["@babel/plugin-proposal-decorators", { "legacy": true }]
]
Christopher Bradshaw
  • 2,615
  • 4
  • 24
  • 38
  • restart the server. used only `"@babel/plugin-proposal-decorators"` – Deke Nov 01 '18 at 15:47
  • Hey would you mind taking a look at this similar issue? I'm using NextJS and Now.sh for deployments: https://stackoverflow.com/questions/54332378/now-sh-build-breaking-due-to-support-for-the-experimental-syntax-decorators-le – Leon Gaban Jan 23 '19 at 17:50
  • 1
    Is there a non-scoped package for plugin-proposal-decorators? I downgraded babel to babel 6 but I need this package to use mobx. All I can find is the scoped versions. – wolfsbane Jul 25 '19 at 08:23
  • @wolfsbane, I don't think they have a non-scoped package for this, but I'm currently using `plugin-proposal-decorators` with mobx. The packages that I think are relevant look like this: `"babel-core": "^6.26.3"`, `"@babel/plugin-proposal-decorators": "^7.1.2"`, `"mobx": "^5.5.1"`. – Christopher Bradshaw Sep 30 '19 at 16:23
  • 1
    When I add that to the plugins, I get this compile error: `ERROR in The "path" argument must be of type string. Received an instance of Array` – jzybert Jan 21 '21 at 15:06
  • Oh my bad. I put it in the plugins section of .eslintrc, not .babelrc – jzybert Jan 21 '21 at 15:12
19

First, execute the command:

npm install customize-cra react-app-rewired @babel/plugin-proposal-decorators --save

Create a new file config-overrides.js at project root and then execute the following:

const { override, addDecoratorsLegacy } = require('customize-cra');
module.exports = override(
 addDecoratorsLegacy()
 );

Also, edit your package.jsonfile :

"scripts": {
 "start": "react-app-rewired start",
 "build": "react-app-rewired build",
 "test": "react-app-rewired test",
 "eject": "react-app-rewired eject"
  },

then restart.

Ulysses
  • 5,616
  • 7
  • 48
  • 84
ulyC
  • 330
  • 3
  • 11
16

Taken from mobxjs. If you're still having issues refer to this. It helped me.

Example config for babel 7, in decorators legacy mode:

//.babelrc

{
    "presets": ["@babel/preset-env"],
    "plugins": [
        ["@babel/plugin-proposal-decorators", { "legacy": true }],
        ["@babel/plugin-proposal-class-properties", { "loose": true }]
    ]
}

Please note that plugin ordering is important, and plugin-proposal-decorators should be the first plugin in your plugin list

"devDependencies": {
    "@babel/core": "^7.1.0",
    "@babel/plugin-proposal-class-properties": "^7.1.0",
    "@babel/plugin-proposal-decorators": "^7.1.0",
    "@babel/preset-env": "^7.1.0"
}

Non-legacy mode decorators (stage 2) is work in progress, see #1732

Edit: updated config to show the non-beta configuration for babel 7

Alex Cory
  • 10,635
  • 10
  • 52
  • 62
  • 1
    Does not work at all. Having both setup in `packages.json` and `.babelrc` changes nothing. – Janusz 'Ivellios' Kamieński Jun 02 '19 at 16:53
  • Did you try doing it in a `babel.config.js`? I was having issues doing it in a `.babelrc` @Janusz'Ivellios'Kamieński – Alex Cory Jun 04 '19 at 00:03
  • 1
    No, I didn't, because there was no clear explanation on how to do that. There are only some scraps laying around and no one gives complete example even. React itself is quite easy to start working with, but going to webpack/babel/node - oh boy, this is surrealistic what happens there for regular developer. Anyway: I solved that simply by throwing out my previous configuration and setting up project with recent CRA and used libs. Luckily that worked in my case. – Janusz 'Ivellios' Kamieński Jun 09 '19 at 12:09
15

I fixed this with yarn add @babel/plugin-proposal-decorators

Then I added the following to babel.config.js in the plugins section:

  [
    require('@babel/plugin-proposal-decorators').default,
    {
      legacy: true
    }
  ],

Finally I needed to restart my webpack dev server.


I haven't tested this but like @christopher bradshaw answers says and according to the babel website if you are using .babelrc for configuration then add the following to the "plugins" section:

  ["@babel/plugin-proposal-decorators", { "legacy": true }]
wuliwong
  • 4,238
  • 9
  • 41
  • 69
10

If you face this error while using ReactJS with MobX, don't enable decorator syntax, but leverage the MobX's built-in decorate utility to apply decorators to your classes / objects.

Don't:

import { observable, computed, action } from "mobx";

class Timer {
  @observable start = Date.now();
  @observable current = Date.now();

  @computed
  get elapsedTime() {
    return this.current - this.start + "milliseconds";
  }

  @action
  tick() {
    this.current = Date.now();
  }
}

Do:

import { observable, computed, action, decorate } from "mobx";

class Timer {
  start = Date.now();
  current = Date.now();

  get elapsedTime() {
    return this.current - this.start + "milliseconds";
  }

  tick() {
    this.current = Date.now();
  }
}
decorate(Timer, {
  start: observable,
  current: observable,
  elapsedTime: computed,
  tick: action
});
Community
  • 1
  • 1
Abhay Kumar
  • 5,048
  • 2
  • 16
  • 21
  • I found this answer most useful! Also found more on the mobX site: https://mobx.js.org/best/decorators.html – jjwallace Mar 09 '20 at 21:14
  • 15
    This is a workaround, not the actual solution to the problem. It's legitimate to choose not to use decorators, but if you decided you want to use decorator syntax in your code, you should set up the configuration to work with them, not give up up because the magical babel incantation necessary is too obscure. – Aaron Greenwald Mar 31 '20 at 06:09
  • 1
    @wuliwong's answer to enable Babel to do its job is what we're after: https://stackoverflow.com/a/55985896/1181545 – hacklikecrack May 04 '20 at 12:12
  • FIY, the decorate has been removed in MobX 6 – FredyC Nov 03 '20 at 09:30
  • 1
    Wohh... Thank you for your explanation. Really helpful. I wasted my 2 days for adapting observable in reactjs and after your answer I tested the scenario and it works. – UGandhi Jun 09 '22 at 21:00
5
  1. Install decorator in package.json
"@babel/plugin-proposal-decorators": "^7.3.0",
"@babel/preset-flow": "^7.0.0"
  1. update babe.config.js with this
module.exports = {
  "presets": [
    "module:metro-react-native-babel-preset",
    "@babel/preset-flow"
  ],
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy" : true }],
    ["@babel/plugin-proposal-class-properties", { "loose" : true }],
  ]
}
Andito
  • 61
  • 1
  • 2
4

Unfortunately none of the mentioned solutions worked for me. Because they need you to run npm run eject first and ... I don't want to do that. To change and override the webpack's configs at runtime, there's a package called react-app-rewired and this is how it should be used:

First install the required dependencies:

npm i --save-dev customize-cra react-app-rewired

Then add a new file called config-overrides.js to the root folder of the project with this content to enable legacy decorators babel plugin:

const {
  override,
  addDecoratorsLegacy,
  disableEsLint
} = require("customize-cra");

module.exports = override(
  // enable legacy decorators babel plugin
  addDecoratorsLegacy(),

  // disable eslint in webpack
  disableEsLint()
);

Finally change the package.json file to use react-app-rewired:

  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
  },

Now run the npm start as usual and enjoy it!

shak
  • 641
  • 9
  • 13
VahidN
  • 18,457
  • 8
  • 73
  • 117
3

As of 2021, with Create React App 4.0, only the following steps are required.

  1. Make sure you do not eject.

  2. npm i --save-dev customize-cra react-app-rewired

  3. Add config-overrides.js with:

const { addDecoratorsLegacy, override } = require('customize-cra')

module.exports = override(addDecoratorsLegacy())
  1. Add babel.config.js with:
module.exports = {
  plugins: [['@babel/plugin-proposal-decorators', { legacy: true }]],
}
  1. Open package.json / scripts section and search-replace react-scripts -> react-app-rewired.
"scripts": {
  "start": "react-app-rewired start",
  "build": "react-app-rewired build",
  "test": "react-app-rewired test",
}

After this, both start, build, and test commands will work with the codebase.

hyperknot
  • 13,454
  • 24
  • 98
  • 153
2

package.json

"@babel/core": "^7.2.2",
"@babel/plugin-proposal-class-properties": "^7.1.0",
"@babel/plugin-proposal-decorators": "^7.1.0",
"@babel/preset-env": "^7.2.3",
"@babel/preset-react": "^7.0.0",
"@babel/register": "^7.0.0",
"babel-loader": "^8.0.5"

webpack.config.js

presets: ["@babel/preset-env", "@babel/preset-react"]

.babelrc

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react"
  ],
  "plugins":  [
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
    ["@babel/plugin-proposal-class-properties", { "loose": true }]
  ]
}
zloctb
  • 10,592
  • 8
  • 70
  • 89
2

To use Mobx with Babel in 2020...

1

npm i babel-preset-mobx

2

module.exports = {
  presets: ['other-presets', 'mobx'],
};

So, just install the mobx preset and add it to your babel configuration file inside the presets array. For example in a babel.config.js etc.

Joe Seifi
  • 1,557
  • 1
  • 12
  • 15
0

I tried to install babel-plugin-transform-inline-environment-variables and it worked.

npm install babel-plugin-transform-inline-environment-variables
Ati
  • 77
  • 5
0

Renamed .babelrc to babel.config.json and it worked!!!

Anton Matiash
  • 172
  • 2
  • 6
0

As of 2021,if you've already “run Eject”,to edit the file called "babelTransform" under the path "/config/jest/BabelTransform",like this:

...
module.exports = babelJest.createTransformer({
  presets: [
    [
      require.resolve('babel-preset-react-app'),
      {
        runtime: hasJsxRuntime ? 'automatic' : 'classic',
      },
    ],
  ],
  "plugins": [
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true,
      }
    ]
  ],
  babelrc: false,
  configFile: false,
});
...

and it worked.

QangLee
  • 1
  • 1
0

I followed this steps and it worked:

1.

npm i --save-dev customize-cra react-app-rewired @babel/plugin-proposal-
        decorators
  1. create in the rro directory config-overrides.js and this is:
const { addDecoratorsLegacy, override } = require('customize-cra')
module.exports = override(addDecoratorsLegacy())
  1. edit package.json scripts
"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject"   
 },

All credits go to this article: https://www.tderflinger.com/en/litelement-react-app

Denise Ignatova
  • 465
  • 4
  • 7