If you are an experienced React engineer and have read numerous articles about the React lifecycle, you may want to close the page.

Please don’t quit so quickly, I want to talk about something different, something from the future.

2018.5.24 update:

React 16.4: getDerivedStateFromProps will trigger when the parent component re-renders it. GetDerivedStateFromProps will trigger when the parent component re-renders it. Including its own setState. The change to further distinguish the method with componentWillReceiveProps, more suitable for asynchronous rendering.

As you all know, there are tons of articles about the React lifecycle, tutorials, and in-depth explanations. So why do I have to redo it? Because the React lifecycle is about to change! The React team is currently working on an asynchronous rendering mechanism to further improve React rendering performance, and in the process they have made a number of drastic lifecycle changes to better accommodate asynchronous rendering.

In short, three lifecycle methods have been removed and two more have been added:

+: Added -: Deleted? : Have change - componentWillMount render componentDidMount componentWillReceiveProps + static getDerivedStateFromProps shouldComponentUpdate - componentWillUpdate + getSnapshotBeforeUpdate ? componentDidUpdate componentWillUnmountCopy the code
class Example extends React.Component {
  static getDerivedStateFromProps(nextProps, prevState) {
    // This lifecycle method is static and is triggered when the component instantiates or receives new props
    // If it returns an object, it will be used to update state; If null, the update of state is not triggered

    / / cooperate ` componentDidUpdate ` use, this method can replace ` componentWillReceiveProps `
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // This method is called "instantaneously" before an actual change (such as a DOM update) occurs, and returns the value as the third argument to 'componentDidUpdate'

    // Used with 'componentDidUpdate', this method can replace 'componentWillUpdate'
  }

  componentDidUpdate(props, state, snaptshot) {
      // The new parameter snapshot is the return value of the previous call to getSnapshotBeforeUpdate}}Copy the code

Detailed interpretation of the

-componentWillMount

This lifecycle method was removed for the following reasons:

  1. In future asynchronous rendering mechanisms, a single component instance may also call this method multiple times
  2. It can be dispersed toconstructorcomponentDidMount

A few examples:

Event binding, asynchronous request

Some inexperienced developers may mistakenly place the code for event binding and asynchronously fetching data in componentWillMount, resulting in

A. Server rendering will trigger this lifecycle method, but memory leaks due to ignoring asynchronously acquired data or not being able to cancel event listening due to server not triggering componentWillUnmount b. Combined with 1., multiple calls can result in repeated requests or repeated listening, which can also lead to memory leaks

Best practices:

class ExampleComponent extends React.Component {
  state = {
    subscribedValue: this.props.dataSource.value,
    externalData: null}; componentDidMount() {// This is only triggered once, so it is safe to make asynchronous requests and event bindings
    this.asyncRequest = asyncLoadData().then(
      externalData= > {
        this.asyncRequest = null;
        this.setState({externalData}); });this.props.dataSource.subscribe(this.handleSubscriptionChange);
  }

  componentWillUnmount() {
    if (this.asyncRequest) this.asyncRequest.cancel();
    // Event binding takes place only once on the client side, where it can be safely unbound
    this.props.dataSource.unsubscribe(this.handleSubscriptionChange);
  }

  handleSubscriptionChange = dataSource= > {
    this.setState({ subscribedValue: dataSource.value });
  };
}
Copy the code

-componentWillReceiveProps & +getDerivedStateFromProps

To see a common componentWillReceiveProps usage:

class ExampleComponent extends React.Component {
  state = {
    isScrollingDown: false}; componentWillReceiveProps(nextProps) {if (this.props.currentRow ! == nextProps.currentRow) {// Update the status and request data when changes are detected
      this.setState({
        isScrollingDown: nextProps.currentRow > this.props.currentRow,
      });
      this.loadAsyncData()
    }
  }

  loadAsyncData() {/ *... * /}}Copy the code

There’s nothing really wrong with this code, but there are better ways to write it. When using getDerivedStateFromProps, you can write:

class ExampleComponent extends React.Component {
  state = {
    isScrollingDown: false.lastRow: null};static getDerivedStateFromProps(nextProps, prevState) {
    PrevProps is no longer provided
    if(nextProps.currentRow ! == prevState.lastRow) {return {
        isScrollingDown: nextProps.currentRow > prevState.lastRow,
        lastRow: nextProps.currentRow,
      };
    }

    // Leave state unchanged by default
    return null;
  }
  
  componentDidUpdate() {
    // Only request data after the update trigger
    this.loadAsyncData()
  }

  loadAsyncData() {/ *... * /}}Copy the code

You can see that in this case, developers will be more “spontaneous” to write code that triggers asynchronous requests at componentDidUpdate (because there’s no alternative :P), avoiding the problem of external components frequently updating multiple props, The component only triggers a single update of its own after batch, so the former is written in a way that leads to unnecessary asynchronous requests, while the latter is more resource-efficient.

-componentWillUpdate & +getSnapshotBeforeUpdate

A common usage for componentWillUpdate is to record the DOM state before the update and then combine it with the DOM state retrieved by componentDidUpdate after the update. The advent of asynchronous rendering makes componentWillUpdate (it is banned in asynchronous rendering, but here we assume it still exists) and componentDidUpdate trigger time interval is large, because asynchronous rendering can suspend the update of this component at any time. As a result, the previous practice becomes unstable because the interval is so long that the DOM may change because of user behavior.

React provides getSnapshotBeforeUpdate for this purpose. It is triggered “instantaneously” before React is modified (usually to update the DOM), making DOM information available there even more reliable than componentWillUpdate. In addition, its return value is passed as a third parameter to componentDidUpdate, which has the obvious benefit of eliminating the need to store data on the component instance that was created to coordinate the state before and after rendering.

Just to summarize

React has been on a rocket since its release of 16, with impressive performance and API evolution. Asynchronous rendering will make its debut in the near future, bringing another breakthrough in rendering performance. In the life cycle changes discussed in this article, you can see how the React team prepared the ground for this change — the removal of old apis, alerting or subtly nudging developers to follow better development practices. Starting with V16.3, the old API will gradually be replaced, and by the time V17 is scrapped, you can start thinking about upgrading your own projects.

Refer to the link: https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html