preface

A decorator is a function that is a syntactic sugar in Es6. It is a class-related syntax for annotating or modifying classes and methods

It is presented as the @+ function name and can precede the definition of classes and class methods

How does it work in React? For example, create-React-app scaffolding projects

Why use decorator mode?

The decorator pattern is more flexible than the design pattern, which gives priority to using objects over class inheritance and dynamically adding extra properties or methods to objects

High-order components are a great thing in React, but one of the most important features is the ability to reuse component logic. Achieve code simplification capability

The premise condition

To use this decorator mode, you need to configure create-React-app, which does not support decorator mode by default. You need to configure your project

Using NPM run eject in the terminal at the root of the project, this command basically does a reverse output of our configuration items, exposing the hidden Webpack configuration items so that the project can be modified, note that it is not reversible

Option 1- Eject and configure in plugins in package.json

To use a decorator, you need to use Babel for the transformation, using the @babel/plugin-proposal-decorators plugin

When you eject some webpack configuration, you’ll see a lot of new files added to the package.json file in the root directory

Configure the plug-in at the Babel object and add @babel/plugin-proposal-decorators to the plugins

{
  "babel": {
    "presets": [
      "react-app"]."plugins": [["@babel/plugin-proposal-decorators",
            { "legacy": true}]}}Copy the code

Pay attention to

The @babel/plugin-proposal-decorators plugin is already installed in the create-react-app scaffolding. `npm install @babel/plugin-proposal-decorators –save-dev

An easy way to do this is to install babel-plugin-transform-decorators-Legacy

{
  "babel": {
    "presets": [
      "react-app"]."plugins": ["transform-decorators-legacy"]}}Copy the code

Pay attention to

If you are using vscode, you can add a jsconfig.json file in the project root directory to eliminate code warnings

{
  "compilerOptions": {
    "experimentalDecorators": true}}Copy the code

Alternatively, tsconfig starts Experimental Decorators in Settings in vscode to resolve this warning

Method 2- Install the Babel plugin in the babelrc configuration

To use this decorator mode, you need to configure create-React-app, which does not support decorator mode by default. You need to configure your project

Use NPM run eject in the create-react-app root directory on the terminal. This command basically prints our configuration items in reverse, exposing the hidden Webpack configuration items so that the project can be modified. Note that it is not reversible

When using decorator mode: Two dependencies need to be installed:

cnpm install -D babel-preset-stage-2
cnpm install -D babel-preset-react-native-stage-0
Copy the code

Then you need to create a.babelrc file in the root directory and do some configuration to the.babelrc file

{
  "presets": ["react-native-stage-0/decorator-support"]}Copy the code

After this configuration, you can use the decorator

Before using the decorator

The following is componentA. Js a higher-order component

import React, { Component } from 'react';

function A(WrappedComponent) {
  // The function takes a Component as an argument and returns a class Component that inherits from Component
  return class componentA extends Component {
    render() {
      return (
        <div>
          <WrappedComponent />
        </div>); }}; }export default A;
Copy the code

The following componentB.js is a component

import React, { Component } from 'react';
import A from './componentA'; // Introduce higher-order components

class componentB extends Component {
  render() {
    return <div>I'm component B</div>; }}export default A(componentB); // Call A directly, passing in the component componentB as an argument
Copy the code

If there are many levels of nesting, you will find this code inelegant and difficult to understand. If you use decorators, you will solve the problem of multiple levels of nesting

Use decorators

In the ComponentB.js component

import React, { Component } from 'react';
import A from './componentA'; // Introduce higher-order components

@A // the name of the function is @+
class componentB extends Component {
  render() {
    return <div>I'm component B</div>; }}export default componentB; // This returns componentB directly
Copy the code

You can add static properties to higher-level components, as well as instance properties

import React, { component } from 'react';

function Foo(params) {
  params.title = 'itclanCoder';
  params.prototype.decorator =
    'Decorators are decorators, @+ function names, used to comment or modify class methods';
}

@Foo
class ComponentA extends Component {
  render() {
    return (
      <div>
        <p>{ComponentA.title}</p>
        <p>{ComponentA.decorator}</p>
      </div>); }}Copy the code

When you call a decorator, you can pass arguments to it, and then you need to return a function. The argument returned by return is the class itself. The following function Foo accepts arguments, which is equivalent to modifying the behavior of the decorator

import React, { component } from 'react';

function Foo(isAble) {
  return function(target) {
    target.isAble = isAble;
  };
}

@Foo(false)
class ComponentA extends Component {
  render() {
    return <div>{componentA.isAble} // false</div>; }}Copy the code

TypeScript

If your project is already working with TypeScript, simply set it to true in the tsconfig.json file

You can use the new ES7 feature decorator

Resolve a problem with vscode not supporting decorator syntax warnings

Create tsconfig.json in the project root directory with the Settings shown below

{
    "compilerOptions": {
        "experimentalDecorators": true."allowJs": true}}Copy the code

Matters needing attention

A decorator changes the behavior of a class at compile time, not run time. This means that the decorator can run the code at compile time, and is itself a function that is executed at compile time

The ⒉ decorator can only be used for classes and methods of classes, not functions, because it has function promotion

conclusion

A higher-order component is a function that takes a component as an argument and returns a component. It allows you to add new functionality to an existing object, add static properties to instance properties, and do not change the structure. It is a wrapper pattern

Because of the decorator property added in Es7, denoted by the @ function name, higher-order components are a very useful thing when writing React components

Perhaps imperceptibly, I have already realized it. Long ago, I saw the decorator mode in the design mode. I have been in a fog and don’t know what is the use of this thing

High-order components can be abbreviated until it is used in React.

If you have any questions about decoration, please leave a message for me and study together

Related reference documents

  • How do I use the @ decorator in React
  • A decorator – a decorator