9

I have understood that since Babel doesn't support decorators out of the box (because it's in early stages of definition) create-react-app doesn't support it as well.

I know that you can eject the generated app and configure Babel to support them, but I don't want to do that.

Finally, libraries like MobX allow you to use decorator's behavior without actually using them, with the help of some utility functions like described at https://mobx.js.org/best/decorators.html

Is there something similar for React?

Pato Loco
  • 1,205
  • 1
  • 13
  • 29

3 Answers3

7

Yes, you can, but you need a couple of things,

Make sure you have react-app-rewired and customize-cra installed so you can override webpack and babel configs

install @babel/plugin-proposal-decorators

and update your config-overrides.js file :

const { override, addBabelPlugin } = require("customize-cra");
const pluginProposalDecorators = require("@babel/plugin-proposal-decorators");

module.exports = override(  
  addBabelPlugin(pluginProposalDecorators)
);
Taki
  • 17,320
  • 4
  • 26
  • 47
  • 2
    For me, this failed because the plugin demanded that one of its options be set. Supposedly you need either "decoratorsBeforeExport" or "legacy" (both boolean options) set, or something? I dunno. For the sake of others new to these tools, here's what ended up working: I replaced the argument to override() with "addBabelPlugin([pluginProposalDecorators, {decoratorsBeforeExport: false}])" and then I referred to https://stackoverflow.com/questions/52628207/an-element-descriptors-kind-property-must-be-either-method-or-field/61542597#61542597 to learn to actually use the plugin without crashing. – mjwach Sep 17 '20 at 00:25
0

It is also possible to use decorators with create-react-app by adding tsconfig.json file to the project that means enabling support for typescript.

You need to set experimentalDecorators to true in compiler options of tsconfig.json

Hope we are aware the .js and .tsx files can co-exist, so whichever file we want to use decorators we can convert to .tsx rest can remain .js files

{
    "compilerOptions": {
        "target": "esnext",
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "skipLibCheck": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "noEmit": true,
        "jsx": "react",
        "noImplicitThis": false, 
        "experimentalDecorators": true,  //<---- 
        "types": ["cypress"]
    },
    "include": ["src"]
}
Akshay Vijay Jain
  • 13,461
  • 8
  • 60
  • 73
0

In my case, it was a combination of plugins

To enable config customization

  1. npm install customize-cra --save-dev
  2. npm install react-app-rewired --save-dev

To enable decorators

  1. npm install @babel/plugin-proposal-decorators --save-dev
  2. npm install reflect-metadata --save-dev
  3. add import 'reflect-metadata' in index.js

Update configs

  1. remove babel config from package.json
  2. create config-overrides.js file in project root
  3. add code:
const { addDecoratorsLegacy, override } = require('customize-cra')

module.exports = override(addDecoratorsLegacy())
  1. Change scrips section in package.json
"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
  },
Tim Kozak
  • 4,026
  • 39
  • 44