A, components,

(1) Function components

If you want to write a component that contains only a Render method and no state, it is easier to use function components. Instead of defining a class that inherits from React.component. we can define a function that takes props as an argument and returns the elements to render.

function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
    {props.value}
    </button>
  );
}
Copy the code


(2) React.Component

ShouldComponentUpdate only checks if props. Color or state.count has changed. If these values do not change, the component will not update

class CounterButton extends React.Component {

  shouldComponentUpdate(nextProps, nextState) {
    if(this.props.color ! == nextProps.color) {return true;
    }
    if(this.state.count ! == nextState.count) {return true;
    }
    return false; }}Copy the code


(3) PureComponent

If your component is more complex, you can use a pattern like “shallow comparison” to check all the fields in props and state to determine if the component needs to be updated. React already provides a handy way to implement this common pattern – you just inherit the React.PureComponent.

class CounterButton extends React.PureComponent {}
Copy the code


In most cases, you can use react. PureComponent instead of shouldComponentUpdate. But it only does shallow comparisons (e.g. 1 == 1 or ture==true, array and object references are the same ***), so if props or state are mutable in some way, shallow comparisons leave something out and you can’t use it.

Do not change objects and arrays in props and state. If you change objects in your parent component, your PureComponent will not update objects. Although the value has been changed, the child component compares references to the previous props to see if they are the same, so no difference is detected.

Therefore, you can force a new object to be returned by using ES6’s ***assign method or the *** array extension operator, or by using a third-party library.

When data structures are complex, things get messy and there are performance issues. Comparing raw values to object references is a low-energy operation. If you have a list of child objects and one of them is updated, it is much faster to check their props and state than to re-render each child node.


(4) When to use Component or PureComponent?

<1> When a Component is independent and the number of components on the page is 1 or 2, the Component has a lot of props, states, and some of them are arrays and objects. The Component needs to be rendered each time, using Component

<2> When components are often subcomponents, as lists, there are a lot of components on the page, there are few props and state properties, and there are almost no arrays or objects in the properties. Components don’t need to be rendered every time, they need to be rendered only when they change, using PureComponent

Subjectively, I think the following components fit into the Component

Button
Input
Copy the code

The following components are suitable for PureComponent

Radio
Checkbox
Option
Copy the code






Higher order functions

HOC (higherOrderComponent) is not itself part of the React API. It is a design pattern based on the composite features of React.

A component converts props to UI, while a higher-order component converts a component to another component. *** components are the basic unit of code reuse in React.

Higher-order components such as Redux’s Connect and Relay’s createFragmentContainer.

(1) HOC does not modify incoming components, nor does it use inheritance to replicate their behavior.

Instead, HOC makes up new components by wrapping them in container components. HOC is a pure function with no side effects.

(2) HOC should pass through props unrelated to itself

HOC adds features to components. They should not change their agreements drastically. HOC should pass through props that are independent of itself, and the component returned by HOC should maintain a similar interface to the original component.

(3) Convention: Wrap the display name for easy debugging of HOC

The container component created will show up in React Developer Tools just like any other component. To facilitate debugging, select a display name to indicate that it is a product of HOC.

The most common approach is to use HOC to wrap the display name of the wrapped component. For example, a higher-order component called withSubscription and the display name for the wrapped component called CommentList would be withSubscription (CommentList) :

function withSubscription(WrappedComponent) {
  class WithSubscription extends React.Component {/* ... */}
  WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)}) `;return WithSubscription;
}

function getDisplayName(WrappedComponent) {
  return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
Copy the code


(4) Precautions:

<1> Do not use HOC in the Render method

render// EnhancedComponent is created every time the render function is called // EnhancedComponent1! == EnhancedComponent2 const EnhancedComponent = enhance(MyComponent); // This will cause subtrees to be unmounted and remounted every time they are rendered!return <EnhancedComponent />;
}
Copy the code


Sometimes it’s useful to define static methods on the React component. For example, the Relay container exposes a static method getFragment to facilitate composing GraphQL fragments.

However, when you apply HOC to a component, the original component will be wrapped with a container component. This means that the new component does not have any static methods of the original component.

/ / define static function WrappedComponent staticMethod =function() {/ *... */} // Now use HOC const EnhancedComponent = enhance(WrappedComponent); . / / enhancement components without staticMethod typeof EnhancedComponent staticMethod = = ='undefined' // trueTo solve this problem, you can copy these methods to the container component before returning:Copy the code

You can automatically copy all non-React static methods using hoist non-react statics:

import hoistNonReactStatic from 'hoist-non-react-statics';
functionenhance(WrappedComponent) { class Enhance extends React.Component {/*... */} hoistNonReactStatic(Enhance, WrappedComponent);return Enhance;
}
Copy the code

In addition to exporting components, another possible solution is to export the static method in addition.

// Use this method instead of... MyComponent.someFunction = someFunction;exportdefault MyComponent; / /... Export the method separately...export{ someFunction }; / /... And import them import MyComponent, {someFunction} from among the components to use'./MyComponent.js';
Copy the code


<3> Refs will not be passed

Although the convention for higher-order components is to pass all props to the wrapped component, this does not apply to refs. That’s because a REF isn’t really a prop – like a key, it’s handled specifically by React. If you add ref to HOC’s return component, the REF reference points to the container component, not the wrapped component.

The solution to this problem is to use the React. ForwardRef API (introduced in React 16.3)


React Reduxconnect

React Redux connect is a high-order function that returns high-order components!

The most common HOC signatures are as follows:

// React Redux 'connect' function const ConnectedComment = connect(commentSelector, commentActions)(CommentList);Copy the code

What just happened? ! If you break it up, it’s easier to see what’s going on.

// connect is a function that returns another function. const enhance = connect(commentListSelector, commentListActions); Const ConnectedComment = enhance(CommentList); // Return HOC, which returns components already connected to the Redux store const ConnectedComment = enhance(CommentList);Copy the code

This form may seem confusing or unnecessary, but it has a useful property. Maximize composability. A single argument like HOC returned by the connect function has a signature Component => Component. Functions whose output type is the same as their input type can be easily combined.

// Instead of this... const EnhancedComponent = withRouter(connect(commentSelector)(WrappedComponent)) // ... You can write the composition utility function // compose(f, g, h) equal to (... args) => f(g(h(... Args))) const enhance = compose(// These are single-parameter HOC withRouter, Connect (commentSelector)) const EnhancedComponent = enhance(WrappedComponent) // (The same attribute also allows connect and other HOC to take on the role of decorators)Copy the code


Four, other

(1) key

Whenever a list is re-rendered, React retrieves the list items that matched each key in the last rendering, based on the key of each list element. If React finds that the current list has a key that didn’t exist before, it creates a new component. If React detects a missing key, it will destroy the previous component. If a component’s key changes, the component is destroyed and a new one is created with the new state.

It is highly recommended that you specify an appropriate key every time you build a dynamic list.

React will warn you if you don’t specify any keys and will use the array index as the default key. But using an array index as a key is problematic when you want to reorder, add, or delete a list.

Specifying key explicitly with key={I} does eliminate warnings, but it still has the same problems as array indexes, so it’s best not to do so in most cases.

The key of a component does not need to be unique globally, only before the current element of the same level.