Changed part

React V16.3 is finally out, and the biggest changes are the following three removed from the lifecycle

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

Two more were added to make up for the loss of the previous three cycles

  • static getDerivedStateFromProps
  • getSnapshotBeforeUpdate

Even though the switching over was slow, and the old three-life cycle was usable throughout the 16 versions, it was important to note that the old life cycle was not allowed in the same component as the new life cycle. Otherwise, an error would be pronounced, “You’re using an unsafe life cycle.”

Why change it

The old lifecycle was complete, capturing almost every state/props/ref of a component update without any logical glitches.

React plans to introduce a new Async Rendering in version 17 that can be interrupted during the construction phase of the virtual DOM before the actual DOM is mounted, i.e. the three life cycles to be removed.

Once life cycle is interrupted, will run again next time you’re back before life cycles, therefore componentWillMount componentWillReceiveProps, None of componentWillUpdate is guaranteed to refresh only once when mounting/getting props/ state changes, so these three methods are marked as unsafe.

Two new life cycles

static getDerivedStateFromProps

  • Trigger time (fix v16.4) : Every time a component is rerender, including after a component build (last executed before render) and every time a new props or state is fetched. As of V16.3, updates to component state do not trigger this lifecycle.
  • Each time a new props is received, an object is returned as the new state. Returning NULL indicates that no state needs to be updated.
  • Cooperate with componentDidUpdate, can cover all usage of componentWillReceiveProps
Class Example extends React.Component {static getDerivedStateFromProps(nextProps, prevState) {// This is a static}}Copy the code

getSnapshotBeforeUpdate

  • Trigger time: Update occurs after render and before component DOM rendering.
  • Returns a value as the third argument to componentDidUpdate.
  • With componentDidUpdate, you can override all usage of componentWillUpdate.
class Example extends React.Component { getSnapshotBeforeUpdate(prevProps, prevState) { // ... }}Copy the code

Summary of Recommended Usage

  1. Initialize state-initializing state

    • Initialize state from constructor
  2. Request data – Fetching External data

    • In componentDidMount request asynchronously loaded data
    • There is an illusion that the data requested in componentWillMount will be available in Render, but in fact, the render will be called almost immediately after willMount, not waiting for the data back, also need to render a “loading” empty data state, So fetching data in didMount has almost no impact.
  3. Adding Event Listeners (or Subscriptions)

    • Add event listeners to componentDidMount
    • React only ensures that componentDidMount-componentWillUnmount can be broken or called multiple times, so there is no guarantee that componentWillMount can be unmounted successfully, and may cause memory leaks
  4. Updating state – Updating state based on props

    • Update the props passed to state with getDerivedStateFromProps(nextProps, prevState)
    • Used instead of componentWillReceiveProps (nextProps nextState), willReceiveProps often misused, led to some problems, so will not recommended to use this method.
    • GetDerivedStateFromProps is a static method, meaning that the instance’s this is not available, so we want to check whether the props are updated before setState
     if(this.props.currentRow ! == nextProps.currentRow) { ... }Copy the code

    Instead, write an extra state for props (‘ ^ ‘)

    if(nextProps.currentRow ! == prevState.lastRow) {return{... lastRow: nextProps.currentRow, }; // Do not update statereturn null
    }
    Copy the code
    • The prevProps parameter is null when invoked for the first time, so every update needs to be performed. React does not record prevProps, so it saves memory
  5. Triggering the request – Invoking External Callbacks

    • The request is triggered by a change in state during the life cycle and is made in componentDidUpdate
    • Why not in componentWillUpdate for the same reason as above 2
  6. – Side effects on props change

    • Visual changes caused by props changes (side effects such as log, GA) are handled in componentDidUpdate
    ComponentDidUpdate (prevProps, prevState) {// componentDidUpdate(prevProps, prevState) {if(this.props.isVisible ! == prevProps.isVisible) {logVisibleChange(this.props.isVisible); }}Copy the code
    • ComponentWillUpdate, componentWillReceiveProps during an update may be triggered multiple times, so the only hope that trigger a side effects should be given to ensure componentDidUpdate triggers only once.
  7. Re-request when props update – External data when props change

    • The incoming new props to asynchronous data, alternative componentWillReceiveProps getDerivedStateFromProps + componentDidUpdate
    // old
      componentWillReceiveProps(nextProps) {
        if (nextProps.id !== this.props.id) {
        	this.setState({externalData: null});
          this._loadAsyncData(nextProps.id);
        }
      }
    Copy the code
    // new
      static getDerivedStateFromProps(nextProps, prevState) {
        // Store prevId in state so we can compare when props change.
        if(nextProps.id ! == prevState.prevId) {return {
            externalData: null,
            prevId: nextProps.id,
          };
        }
        // No state update necessary
        return null;
      }
      componentDidUpdate(prevProps, prevState) {
        if(this.state.externalData === null) { this._loadAsyncData(this.props.id); }}Copy the code
  8. Record the original DOM node property before the update – Reading DOM Properties before an update

    • Get the DOM node before upate, getSnapshotBeforeUpdate(prevProps, prevState) instead of componentWillUpdate(nextProps, nextState)
    • GetSnapshotBeforeUpdate after Render but before the node is mounted
    • ComponentDidUpdate (prevProps, prevState, Snapshot) gets the DOM property value returned by getSnapshotBeforeUpdate directly

Life cycle function replacement overview

static getDerivedStateFromProps(nextProps, prevState) { 4. Updating state based on props 7. Fetching external data when props change // Clear out previously-loaded  data so we dont render stale stuff }constructor() {
	1. Initializing state
  }
  componentWillMount() {
  	// 1. Initializing state
  	// 2. Fetching external data
  	// 3. Adding event listeners (or subscriptions)
  }
  componentDidMount() {
	2. Fetching external data
	3. Adding event listeners (or subscriptions)
  }
  componentWillReceiveProps() {
  	// 4. Updating state based on props
  	// 6. Side effects on props change
  	// 7. Fetching external data when props change
  }
  shouldComponentUpdate() {
  }
  componentWillUpdate(nextProps, nextState) {
  	// 5. Invoking external callbacks
  	// 8. Reading DOM properties before an update
  	
  }
  render() {
  }
  getSnapshotBeforeUpdate(prevProps, prevState) {
	8. Reading DOM properties before an update
  }
  componentDidUpdate(prevProps, prevState, snapshot) {
	5. Invoking external callbacks
	6. Side effects on props change
  }
  
  componentWillUnmount() {}Copy the code

The last

The above content is basically combined with some of my experience half translation and half summary, there are inaccurate places welcome to correct.

For more details are interested can go to the official documentation, https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html

For async – rendering or for Dan little brother are interested can go to see him in front of meeting a little demo: https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react-16.html