Search code examples
javascriptreactjslifecycle

How to use lifecycle method getDerivedStateFromProps as opposed to componentWillReceiveProps


It looks like componentWillReceiveProps is going to be completely phased out in coming releases, in favor of a new lifecycle method getDerivedStateFromProps:static getDerivedStateFromProps().

Upon inspection, it looks like you are now unable to make a direct comparison between this.props and nextProps, like you can in componentWillReceiveProps. Is there any way around this?

Also, it now returns an object. Am I correct to assume that the return value is essentially this.setState?

Below is an example I found online: State derived from props/state.

Before

class ExampleComponent extends React.Component {
  state = {
    derivedData: computeDerivedState(this.props)
  };

  componentWillReceiveProps(nextProps) {
    if (this.props.someValue !== nextProps.someValue) {
      this.setState({
        derivedData: computeDerivedState(nextProps)
      });
    }
  }
}

After

class ExampleComponent extends React.Component {
  // Initialize state in constructor,
  // Or with a property initializer.
  state = {};

  static getDerivedStateFromProps(nextProps, prevState) {
    if (prevState.someMirroredValue !== nextProps.someValue) {
      return {
        derivedData: computeDerivedState(nextProps),
        someMirroredValue: nextProps.someValue
      };
    }

    // Return null to indicate no change to state.
    return null;
  }
}

Solution

  • About the removal of componentWillReceiveProps: you should be able to handle its uses with a combination of getDerivedStateFromProps and componentDidUpdate, see the React blog post for example migrations. And yes, the object returned by getDerivedStateFromProps updates the state similarly to an object passed to setState.

    In case you really need the old value of a prop, you can always cache it in your state with something like this:

    state = {
      cachedSomeProp: null
      // ... rest of initial state
    };
    
    static getDerivedStateFromProps(nextProps, prevState) {
      // do things with nextProps.someProp and prevState.cachedSomeProp
      return {
        cachedSomeProp: nextProps.someProp,
        // ... other derived state properties
      };
    }
    

    Anything that doesn't affect the state can be put in componentDidUpdate, and there's even a getSnapshotBeforeUpdate for very low-level stuff.

    UPDATE: To get a feel for the new (and old) lifecycle methods, the react-lifecycle-visualizer package may be helpful.