React life cycle and common usage scenarios

Preface

The life cycle of React has always been very important at work. We often need to do what we need in the required time period. In React, the life cycle can be roughly divided into initialization (Initialization), mounting (Mounting), In the Updating and Unmounting phases, each phase will call different life cycle functions. Of course, with the update of the react version, there will be relative changes, so let's refer to the summary now.

Most teams will not necessarily follow up and upgrade to version 16, so the life cycle before 16 is still necessary to master, not to mention that 16 is also based on previous modifications
Insert picture description here

Initialization

That is, the construction method (constructor()) of the class in the following code. The Test class inherits the base class of react Component, and also inherits the base class of react, so that the methods such as render() and life cycle can be used. This also shows The reason why functional components cannot use these methods. super(props) is used to call the construction method (constructor()) of the base class, and also inject the props of the parent component into the child component, and read the child component (props in the component are read-only and immutable, and the state is variable). The constructor() is used to initialize some components, such as defining the initial content of this.state.

Note:
constructor Does not count as life cycle function. constructorWe call it the constructor, which is the basic syntax of ES6. Although it has the same properties as the life cycle function, it cannot be considered a life cycle function. But you have to think of it as a life cycle function in your heart. I personally regard it as a Initializationstage of React , defining properties (props) and state (state).

import React, {
    
     Component } from 'react'
class Test extends Component {
    
    
  constructor(props) {
    
    
  super(props)
  }
}

Mounting in the second stage

  1. componentWillMount: Execute when the component is about to be mounted on the page.

Called before the component is mounted to the DOM, and it will only be called once. Calling this.setState here will not cause the component to re-render. You can also advance the content written here to the constructor(), so the project is very use less.

  1. render: Execute when the page state or props change.

According to the component's props and state (without retransmission and re-assignment of the two, whether the argument changes, can cause the component to re-render), return a React element (describe the component, that is, the UI), and is not responsible for the actual rendering of the component. Then React itself renders the page DOM based on this element. Render is a pure function (Pure function: the return result of the function only depends on its parameters; there are no side effects in the execution of the function). This.setState cannot be executed in it, and there will be side effects of changing the state of the component.

  1. componentDidMount: Executed when the component is mounted.

Called after the component is mounted to the DOM, and will only be called once

export default class App extends Component {
    
    
  componentWillMount () {
    
    
    console.log('componentWillMount----组件将要挂载到页面的时刻')
  }
  render() {
    
    
    console.log('render---组件挂载中.......')
    return (
      <div>
        <TodoList/> 
        <ReduxTodoList/>
      </div>
    )
  }
  componentDidMount () {
    
    
    console.log('componentDidMount----组件挂载完成的时刻执行')
  }
}

Printed result:

componentWillMount----组件将要挂载到页面的时刻执行
render----开始挂载渲染
componentDidMount----组件挂载完成的时刻执行

这就是挂载阶段的生命周期的执行顺序,当然他跟书写顺序没有关系

Note:
componentWillMount And componentDidMountthese two life cycle functions are only executed once when the page is refreshed, and the render function is executed as long as there are changes in state and props. This beginner must pay attention.

Three update stage Updation

This stage is a more complicated stage. From the figure above, it can be seen that there are two types of component updates. It is necessary to clarify the React component update mechanism. The state update caused by setState or the props update caused by the re-render of the parent component. The updated state and props will cause the re-render of the child component regardless of whether there is a change relative to the previous one.

  1. shouldComponentUpdateBefore the component is updated, it is automatically executed. It requires a boolean result to be returned. It must have a return value. Here it directly returns a true (in real development, this is of great use and can effectively solve performance problems. ), if you return false, the component will not be updated. To put it simply, if you return true, you agree to the component update; if you return false, you oppose the component update. This method compares nextProps, nextState and the this.props, this.state of the current component. When it returns true, the current component will continue to perform the update process, and return false to stop the current component update, which can be used to reduce unnecessary rendering of the component and optimize Component performance.

  2. componentWillUpdateBefore the component is updated, but shouldComponenUpdateafter it is executed, but when the shouldComponenUpdatereturn is false, the update of the component will be opposed, and this function will not be executed

  3. componentDidUpdateExecuted after the component is updated, it is the last part of the component update

export default class App extends Component {
    
    
  shouldComponentUpdate () {
    
    
    console.log ('1.shouldComponentUpdate----组件更新之前')
    return true
  }
  componentWillUpdate () {
    
    
    console.log ('2.componentWillUpdate---组件更新前,shouldComponentUpdate函数之后执行 ')
  }
  render() {
    
    
    console.log('3.render---组件挂载渲染.......')
    return (
      <div>
        <TodoList/> 
        <ReduxTodoList/>
      </div>
    )
  }
  componentDidUpdate () {
    
    
    console.log('componentDidUpdate----组件更新完成的时刻执行')
  }
}

Print results and execution order

1-shouldComponentUpdate---组件发生改变前执行
2-componentWillUpdate---组件更新前,shouldComponentUpdate函数之后执行
3-render----开始挂载渲染
4-componentDidUpdate----组件更新之后执行
  1. So componentWillReceivePropswhen will the above figure be executed? In fact, the child component receives the parameters passed by the parent component, and the parent component's render function is executed again, and this life cycle will be executed.
    Note: The function will not be executed when the
    used componentWillReceivePropscomponent exists in the Dom for the first time;
    if it already exists in the Dom, the function will be executed.
    It will be called when the props passed by the parent component is about to cause the component to be updated. This method accepts a parameter that refers to the latest props status data passed by the current parent component to the component. In this life cycle method, we can find out whether props have changed based on comparing the values ​​of the new and old props of nextProps and this.props, and do some data processing logic in turn.

Unmounting

There is only one life cycle function at this stage: componentWillUnmountThis method is called before the component is uninstalled. You can perform some cleaning work here, such as clearing the timer used in the component, clearing the componentDidMountmanually created DOM elements, unbinding events, etc. Avoid causing memory leaks

Summarize the optimization page that uses the life cycle function:

  1. componentDidMountRequest ajax in the life cycle function, it is recommended to execute it in the componentDidMount function, because it is executed in the render, there will be many problems, such as the loop rendering; if it is executed in the componentWillMount, there will be conflicts when using RN. Therefore, it is strongly recommended to make an ajax request in the componentDidMount function.
  2. When the parent component is updated and passed to the child component, the pros is changed anyway, the render function of the child component is constantly triggered, and performance problems occur. We can generally occur in the update phase, so use shouldComponentUpdate
shouldComponentUpdate(nextProps,nextState){
    
    
    if(nextProps.content !== this.props.content){
    
    
        return true
    }else{
    
    
        return false
    }

}

The life cycle of React v16.4

Insert picture description here

Reason for change

It turns out that the life cycle (before React v16.0) is not suitable after the Fiber launched in React v16 , because if async rendering is to be turned on, all functions before the render function may be executed multiple times.
What is the original (before React v16.0) life cycle that was executed before render?

  • componentWillMount
  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate

If the developer opens async rendering and makes A JAX requests with the lifecycle methods executed before the above render, then AJAX will be called multiple times needlessly. . . Obviously not the result we expected. Moreover, when AJAX is initiated in componentWillMount, no matter how fast the result is obtained, it will not be able to keep up with the first render, and componentWillMount will also be called for server-side rendering (of course, this may be the expected result). Such IO operations are more suitable in componentDidMount.

Ban can not be better than the effect of persuasion developers do not use this, so in addition to shouldComponentUpdate, all other functions before the render function ( componentWillMount, componentWillReceiveProps, componentWillUpdate) have been getDerivedStateFromPropsreplaced.

That is to use a static function getDerivedStateFromPropsto replace the deprecated several life cycle functions, which is to force the developer to only do side-effect-free operations before rendering, and the operations that can be done are limited to determining the new state based on props and state

Two new life cycle functions are newly introduced:

1. getDerivedStateFromProps

getDerivedStateFromProps originally (in React v16.3) is only created and updated (the part triggered by the parent component), that is, it is not triggered by the parent component, then getDerivedStateFromProps will not be called, such as its own setState trigger or forceUpdate trigger
. bit of a mess, to correct this in React v16.4, so that getDerivedStateFromProps either Mountingor Updating, and regardless of what caused because Updating, all will be called, specifically to see the life cycle of Figure React v16.4.
getDerivedStateFromProps(props, state) is called before the render method when the component is created and when it
is updated . It should return an object to update the state, or return null to not update anything.

Whenever the parent component triggers the rendering of the current component, getDerivedStateFromProps will be called, so that we have the opportunity to adjust the new state based on the new props and the previous state. If you put it in the three deprecate life cycle functions that are relatively pure and have no side effects, you can move to getDerivedStateFromProps; if you unfortunately do something like AJAX, you must first reflect on why you did it in the first place, and then move to componentDidMount Or go to componentDidUpdate. At present, when you use the three deprecated life cycle functions, there will be a red warning in development mode, requiring you to use the UNSAFE_ prefix. It may be discarded when a major version update is launched, so those developers who are lucky enough to give up use it.

2. getSnapshotBeforeUpdate

getSnapshotBeforeUpdate() is called after the render, when the DOM can be read but cannot be used. It allows your component to capture some information (such as scroll position) from the DOM before it may change. Any value returned by this lifecycle will be passed as a parameter to componentDidUpdate().
Examples given on the official website:

class ScrollingList extends React.Component {
    
    
  constructor(props) {
    
    
    super(props);
    this.listRef = React.createRef();
  }
  getSnapshotBeforeUpdate(prevProps, prevState) {
    
    
    //我们是否要添加新的 items 到列表?
    // 捕捉滚动位置,以便我们可以稍后调整滚动.
    if (prevProps.list.length < this.props.list.length) {
    
    
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }
  componentDidUpdate(prevProps, prevState, snapshot) {
    
    
    //如果我们有snapshot值, 我们已经添加了 新的items.
    // 调整滚动以至于这些新的items 不会将旧items推出视图。
    // (这边的snapshot是 getSnapshotBeforeUpdate方法的返回值)
    if (snapshot !== null) {
    
    
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }
  render() {
    
    
    return (
      <div ref={
    
    this.listRef}>{
    
    /* ...contents... */}</div>
    );
  }
}

Note:
When you use the new life cycle API of getDerivedStateFromProps, getSnapshotBeforeUpdate and the deprecate life cycle function at the same time, the deprecate life cycle function will be directly ignored and will not be executed in time!

Guess you like

Origin blog.csdn.net/pz1021/article/details/105020070