This is the 10th day of my participation in the August More Text Challenge. For details, see:August is more challenging

The React extension

Use of setState, lazyLoad, Context, component optimization, PureComponent, error bounds

A, setState

Object setState is the syntactic sugar of functional setState. If the new state is dependent on the original state, use object setState, and if it is dependent, use function setState (for example, change count to count+1).

  1. Object setState:

    const {count} = this.state; //count=0 setState(count:count+1, [callback]); console.log(this.state.count); / / 0Copy the code

    This is an optional callback function that will be called only after the state has been updated and the interface has been updated (after the render call).

    Since our setState is executed asynchronously, the value of this.state.count in the next setState statement will remain unchanged. If you want to use this.state.count to get the changed value and process it, You can call the callback function.

  2. The function setState:

    this.setState(state => ({ count: state.count + 1 }));
    Copy the code

    The first argument to the setState function is an updater function that can receive both state and props, so there is no need to take the value from this.state in advance. The second argument is the same as the callback function.

Second, the lazyLoad

Sometimes when we have a lot of routes, we don’t want to load all the routes the first time we enter the page, but wait until we need to load them, which is when lazy loading is used.

Reference a lazy function in React and use lazy to introduce components

Import React, {Component, lazy, Suspense} from 'React' const Home = lazy(() => import('./Home')Copy the code

In addition to this, you need to use Suspense components to enclose all the places where routing is registered, and then specify a fallback(which can be a component) for Suspense;

<Suspense fallback={<h1>loading... </h1>}> <Route path="/home" component={Home}> </Suspense>Copy the code

Third, fragments

We often use a div as the wrapping tag when we render the page. This div may not be useful after rendering the page, so if we don’t want this extra div, we can use the

tag instead, or use the empty <> tag instead.

<Fragment key={111}></Fragment>
<></>
Copy the code

However, empty tags cannot be used to place a value. For example, fragments can be used to place a key but empty tags cannot be used.

Fourth, the Context

Context is a means of communication between components. It is usually used to communicate between grandparent and grandparent components.

There may be A situation where component A has COMPONENT B and component B has component C; A passes the value to component C, but component B does not need it; Context can be used in this case, using the following steps:

  1. Create the Context object

    const MyContext = React.createContext(); const {Provider, Consumer} = MyContext; <Provider value={{username, age}}> <B/> </Provider>Copy the code

    After this setting, there is no further processing in component B and C within component B. Component B and its children can receive the value. You can also pass multiple values to a Context;

    • (1) static contextType = myContext; (2) Username can be found in this.context; (3) Static contextType = myContext;

    • Second: Both function components and class components can be used. One more Consumer component is required than the first method

      <Consumer>
          {
              value=> {
                  return `${value.username}, ${value.age}`;
              }
          }
      </Consumer>
      Copy the code

    In application development, you don’t usually use Context. You usually use the React plug-in, such as React-Redux.

V. Component optimization

Component problem

  1. As long as the executionsetStateThe component is regenerated even if the state data is not changedrender()
  2. As long as the current component rerender()Even if the child component does not use any of the parent’s data, it is automatically re-createdrenderChild components

Both cases result in inefficiency because shouldComponentUpdate() in the Component always returns true. If we want to improve efficiency, we need to make it render() only when the component’s state or props data changes. There are two ways to solve this problem:

rewriteshouldComponentUpdate()Methods (PureComponent)

This method can retrieve the props and state to be changed. At this point, we can compare the props and state to the current props and state, and return false if they are the same, thus preventing render() from happening.

shouldComponentUpdate(nextProps, nextState) {
    if(this.state === nextState)  return  false
    else return true
}
Copy the code

To make a child component independent of its parent component, compare props. PureComponent (component.component.update) {shouldComponentUpdate (component.component.update);}

But PureComponent has a downside:

  • Just forstateandpropsIf only one data inside the object is changed,shouldComponentUpdateIt still returns false to blockrender()For;
  • In other words, we can’t modify it directlystateData, but to produce new data
Const obj = this.state; // this.setstate ({name: 'mannqo'}) ¶ Name = 'aaa'. Name = 'mannqo' console.log(obj === this.state); // true this.setState(obj);Copy the code

PureComponent is commonly used in projects for optimization

Six, render props

Dynamically passing labels with content to components, such as:

The contents of the tag body can be obtained at this.props. Children;

children props

import React, { Component } from 'react' export default class Parent extends Component { render() { return ( <div><A><B /></A></div> ) } // We need {this.props. Children} in component A to introduce component BCopy the code

If component B needs to use data from component A, it can’t be obtained using this.props. This refers to Parent, not component A. Render props are used when you encounter this scenario in development.

3, render props: this is the method for passing data from A to A

< A render = {(name) = > < name = B / > {name}} / > / / in the parent {this. Props. Render (name)} / / A componentCopy the code

In A enclosing of A state. The name data transmission, the parent component of the parent component calls A render can get from A component name value passed in the past, and the B component rendering;

6. Error Boundary

This error boundary can only be used in a production environment, that is, after packaging.

Sometimes there may be some unknown errors. We need to minimize the impact of this error as much as possible. An error boundary is to limit the error to a certain range.

GetDerivedStateFromError is raised with an error message when a child of Parent reports an error. Use with componentDidCatch, used for statistics page errors, send requests to the background

state = {hasError: } export Default Class Parent extends Component {static getDerivedStateFromError(error) {return {hasError: error} } componentDidCatch(error, info) { console.log(error, info); } render() {return (<div> <h2>Parent component </h2> {this.state.haserror? </h2> : <Child/>} </div>)}}Copy the code

Features: It can only capture errors generated during the life cycle of descendant components (such as errors in Render). It cannot capture errors generated by its own components and errors generated by other components in the composition time and timer.