React In-Depth Series 4: Component Lifecycle

Text: Xu Chao, author of "The Road to Advanced React"

Authorized to publish, reprint please indicate the author and source


React In-Depth Series 4: Component Lifecycle

React in-depth series, in-depth explanation of the key concepts, features and patterns in React, to help you deepen your understanding of React and use React more flexibly in your projects.

Components are the basic units for building React applications. Components need to have the capabilities of data acquisition, business logic processing, and UI rendering, and these capabilities depend on the different lifecycle methods of components. The life cycle of a component is divided into three phases: mount phase, update phase, and unload phase. Each phase contains corresponding lifecycle methods. Because it is an in-depth series of articles, this article will not introduce the use of each life cycle method in detail, but will focus on the questions and wrong usage methods that are often encountered when using the component life cycle.

server data request

When beginners use React, they often do not know when to send a request to the server to get the data required by the component. For the initial data required by the component, the most suitable place is to make a data request in the componentDidMount method. At this time, the component is mounted, and the DOM represented by it has been mounted on the DOM tree of the page, even if the obtained data is obtained. It is absolutely safe to operate DOM nodes directly. Some people are also accustomed to requesting data in constructor or componentWillMount, thinking that this can get data faster, but the time ahead of them is very small compared to the execution time of componentDidMount. In addition, when server rendering (SSR), componentWillMount will be called twice, once on the server side and once on the client side, which will cause additional requests to occur.

Another scenario for a component to make a data request: The component's props are changed due to the update of the parent component. If the component's data request depends on the props, the component needs to make a data request again. For example, the news detail component, NewsDetail, needs to pass the id of the news as a parameter to the server when obtaining the news detail data. When the NewsDetail is already in the mounted state, if you click on other news, the componentDidMount of the NewsDetail will not be called again, so componentDidMount The method that makes a news detail data request in , will also not be executed again. At this time, the data request should be made in componentWillReceiveProps:

componentWillReceiveProps(nextProps) {
  if(this.props.newId !== nextProps.newsId) {
    fetchNewsDetailById(nextProps.newsId)  // 根据最新的新闻id,请求新闻详情数据
  }
}

If the timing of the data request is triggered by the interactive behavior on the page, for example, after clicking the query button to query the data, you only need to execute the data request in the event listener function of the query button. This situation is generally There will be no doubt.

Update phase method call

Updating a component is the most complex phase in the component lifecycle and the one involving the most lifecycle methods.

Normally, when a component is updated, the calling sequence of the component's lifecycle methods is as follows:

componentWillReceiveProps -> shouldComponentUpdate -> componentWillUpdate -> render -> componentDidUpdate

// 组件收到新的props(props中的数据并不一定真正发生变化)-> 决定是否需要继续执行更新过程 -> 组件代表的虚拟DOM即将更新 -> 组件重新计算出新的虚拟DOM -> 虚拟DOM对应的真实DOM更新到真实DOM树中

When the parent component is updated or the component itself calls setState, it will cause the component to update. The component update caused by the update of the parent component, the invocation of the life cycle method is the same as above. If the component itself calls setState, the component is updated, and the life cycle method is called as follows:

shouldComponentUpdate -> componentWillUpdate -> render -> componentDidUpdate

It can be seen that componentWillReceiveProps will not be called in this case.

When the component's shouldComponentUpdate returns false, the component will stop the update process. At this time, the calling sequence of the lifecycle methods is as follows:

componentWillReceiveProps -> shouldComponentUpdate -> 结束

or (the component itself calls setState, causing the component to update):

shouldComponentUpdate -> 结束

Timing of setState

There are many life cycle methods of components. In which methods can you call setState to update the component state? Which methods are not possible?

  • possible way

componentWillMount、componentDidMount、componentWillReceiveProps、componentDidUpdate

Here are a few notes:

  1. Synchronous calls to setState in componentWillMount will not cause additional rendering of the component. The lifecycle methods experienced by the component are componentWillMount -> render -> componentDidMount, and the component will not be updated again because of the setState call in componentWillMount. If setState is called asynchronously , the component will perform additional update operations. However, in actual scenarios, setState is rarely called in componentWillMount. Generally, it can be replaced by directly defining state in the constructor.
  2. Under normal circumstances, when setState is called, the component will perform an update process, and the methods in the update phase such as componentWillReceiveProps will be called again, but if setState is called in componentWillReceiveProps, it will not cause a new update process, that is, After the current update process is over, the update phase methods such as componentWillReceiveProps will not be called again. (Note that this still refers to calling setState synchronously . If it is called asynchronously, it will cause the component to render again)
  3. Be extra careful when calling setState in componentDidUpdate. Conditional judgment must be made before setState. Only if the corresponding conditions are met, setState will be set. Otherwise, the group component will continue to perform the update process and enter an infinite loop. Because setState will cause a new component update, after the component update is completed, componentDidUpdate is called, and the setState is continued, and an infinite loop occurs.
  • impossible way

No other lifecycle methods can call setState for two main reasons:

  1. Create an infinite loop. For example, when setState is called in shouldComponentUpdate, componentWillUpdate and render, the component update has not been completed, and it will enter a new round of update, resulting in continuous cyclic update and entering an infinite loop.
  2. meaningless. When componentWillUnmount is called, the component is about to be unmounted, and setState is to update the component. It is obviously meaningless to update the state on a component that is about to be unmounted. In fact, calling setState in componentWillUnmount will also throw an exception.

Render times!= The number of times the browser interface is updated

Take a look at the following example:

class App extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      bgColor: "red"
    }
  }

  render() {
    var {bgColor} = this.state
    return (
      <div style = {{backgroundColor: bgColor}}> 
        Test
      </div>
    );
  }
  
  componentDidMount() {
    this.setState({
      bgColor: "yellow"
    })
  }
}

When we observe the page rendered by the browser, the background color of the div where Test is located in the page first shows red and then turns yellow? Or is it just displayed in yellow?

The answer is: it is displayed in yellow directly!

During this process, the lifecycle methods of components are called in the following order:

constructor -> componentWillMount -> render -> componentDidMount -> shouldComponentUpdate -> componentWillUpdate -> render -> componentDidUpdate

After the component is mounted, an update process will be performed immediately due to the call of setState. Although the render method is called twice, this does not cause the browser interface to be updated twice. In fact, the two DOM modifications are merged into one browser interface update. React's official website also has the following instructions when introducing the componentDidMount method:

Calling setState() in this method will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won’t see the intermediate state.

This shows that the number of component renders is not necessarily equal to the number of browser interface updates. Although the execution of JS and the rendering of DOM are completed by different threads of the browser, the execution of JS will block the rendering of DOM, and the above two renders are executed in a JS event cycle, so before the two renders end , the browser will not update the interface.

Next notice:

React In-Depth Series 5: Event Handling


New book recommendation "The Road to Advanced React"

Author: Xu Chao

Graduated from Zhejiang University with a master's degree, senior front-end engineer, long-term working in the energy Internet of things company Envision Intelligence. 8 years of software development experience, familiar with big front-end technology, rich experience in web front-end and mobile terminal development, especially in-depth understanding and practical experience of React technology stack and mobile Hybrid development technology.



The front-end team of the Meituan-Dianping advertising platform is recruiting front-end interns for 2019/2020 (in the direction of dynamic effects)

Interested parties email: [email protected]

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324719031&siteId=291194637