Short description of the article

  • Intro

  • If you have access to the babel configuration:

    • Enabling the Decorator’s syntax using Babel 6

    • Enabling the Decorator’s syntax using Babel 7

  • Enabling the Decorator’s syntax using Create React App (v2):

    • Enabling the Decorator’s syntax using Typescript

    • Enabling the Decorator’s syntax using Fork

    • Enabling the Decorator’s syntax using Eject

    • Enabling the Decorator’s syntax using the “customize-cra” npm package

  • Conclusion

Intro

I have been working as an Angular developer for more than 3 years now and have always been excited by the many out-of-the-box solutions that are offered by an Angular framework.

Today, I’ve decided to tell you about Decorators - one of the most fundamental parts in Angular. Precisely, the article will elaborate on the little instructionto how incorporate this feature into React. Firstly, let me remind you what the decorators are and what new and useful options they offer.

In general, Decorators are just pure functions with arguments that can dynamically attach to the object additional functionality prior to its usage. To be more precise, with their help you can:

  • check the condition of the environment before the function execution;

  • carry out the postponed initialization;

  • do logging/tracing;

  • precisely extend the code written by someone else;

  • do many other things...

I fell in love with decorators functionality in 2016 when Angular 2 had been released. So, it has been already three years since then and nowadays still only a few people use decorators in React. How do you think what might be the reasons for that?

The main reason is the attitude of the React core team - you can get a more precise answer in their official documentation. Therefore, there’s still a lack of the opportunities for using decorators out-of-the-box in React, despite the fact that there are many developers who are interested in such a feature. In this article, I’m going to explain how to use them.

1. If you have access to the Babel configuration

Enabling the Decorator’s syntax using Babel 6:

For enabling the decorator support you should run:

npm i --save-dev babel-plugin-transform-decorators-legacy

And make a change to a .babelrc file:

{
  "presets": ["es2015", "stage-1"],
  "plugins": ["transform-decorators-legacy"]
} 

Enabling Decorator syntax using Babel 7:

For enabling the decorator support you should run:

npm i --save-dev @babel/plugin-proposal-class-properties
npm i --save-dev@babel/plugin-proposal-decorators

And make a change to a .babelrc file:

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

2. Enabling the Decorator’s syntax using Create React App (v2)

Enabling the Decorator’s syntax using Typescript:

Using Typescript is the easiest way of enabling decorators in React because it doesn’t require any tricks. You only have to perform several steps:

  • Run in the terminal: ```npx create-react-app my-typescript-app --typescript```

  • Reload compilerOptions in the “tsconfig.json” file by adding emitDecoratorMetadata and experimentalDecorators:

"compilerOptions": {
  "target": "es5",
  "allowJs": true,
  "skipLibCheck": false,
  "esModuleInterop": true,
  "allowSyntheticDefaultImports": true,
  "emitDecoratorMetadata": true,
  "experimentalDecorators": true,
  "strict": true,
  "forceConsistentCasingInFileNames": true,
  "module": "esnext",
  "moduleResolution": "node",
  "resolveJsonModule": true,
  "isolatedModules": true,
  "noEmit": true,
  "jsx": "preserve"
  },

Literally, I find it one of the best options because I like Typescript. Using Typescript comes up with the benefit of linting your code, static-typing, and overall, better code quality. You can check out our team's repository at GitHub as an example of using decorators with Typescript .

Enabling the Decorator’s syntax using Fork

As for me, the Fork method is the best choice for the build customization. Besides, this option is supported by Dan Abramov - one of the influencers in the React team. The project fork of react-scripts is an alternative to Eject, other words to say, it doesn’t contain the cons of Eject, but has its own different nuances.

Also, please have a chance to read the article about Customizing CRA without Eject, where you can find more detailed information on forking CRA repository and using it within your project.

Enabling the Decorator’s syntax using Eject

For decorator enabling you should just follow a few steps:

  • run in the command prompt:

npm run eject

  • install babel plugins by executing the following commands:

npm i -D @babel/plugin-proposal-decorators
@babel/plugin-proposal-class-properties

  • update Babel in a package.json file by adding plugins to it:

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

This command will remove the single build dependency from your project. It will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you’d have the full control over them. At our repository you can see an example of enabling the Decorator’s syntax using Eject .

Enabling the Decorator’s syntax using the “customize-cra” npm package

If you create the project by using the ```npx create-react-app my-app``` command, then you won’t have a chance to use decorators out-of-the-box. And in order to do it, you need to install the “customize-cra” package as it was did by our team at GitHub's repository.

Then you should update devDependencies in the “package.json” file by adding to it 2 packages - “customize-cra” and “react-app-rewired”. A second package is necessary to enable the 1st package.

"devDependencies": {
  "customize-cra": "^0.2.8",
  "react-app-rewired": "^1.6.2"
}

Afterward, you should update the scripts in the “package.json” file by replacing react-scripts with “react-app-rewired”.

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

Finally, add a “config-overrides.js” file to the root of the project that enables the Decorator’s syntax. File contents:

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

module.exports = override(
 addDecoratorsLegacy(),
);

That is an easy way of enabling the Decorator’s syntax as it requires minimal changes in the project. However, such an approach has its own consequences: it might stop working within future versions of the “react-scripts”. In case it will happen,you’d have to use the “Eject” or “Fork” approaches described above.

Conclusion

All in all, as you know Decorators provide us with many benefits and the possibility to derive a profit from their vast functionality is a great chance for any developer. In this article, I’ve revealed several approaches of enabling the Decorator’s syntax in React application and considered the benefits and drawbacks they have. It’s totally up to you what approach to choose, my main point is: be on a roll - implement, use and retrieve all benefits from decorators now.

In case, you have any questions or a piece of advice for your new project, feel free to contuct us!