How to use lifecycle method getDerivedStateFromProps as opposed to componentWillReceiveProps

JavascriptReactjsLifecycle

Javascript Problem Overview


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;
  }
}

Javascript Solutions


Solution 1 - Javascript

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.

Solution 2 - Javascript

As we recently posted on the React blog, in the vast majority of cases you don't need getDerivedStateFromProps at all.

If you just want to compute some derived data, either:

  1. Do it right inside render
  2. Or, if re-calculating it is expensive, use a memoization helper like memoize-one.

Here's the simplest "after" example:

import memoize from "memoize-one";

class ExampleComponent extends React.Component {
  getDerivedData = memoize(computeDerivedState);

  render() {
    const derivedData = this.getDerivedData(this.props.someValue);
    // ...
  }
}

Check out this section of the blog post to learn more.

Solution 3 - Javascript

As mentioned by Dan Abramov > Do it right inside render

We actually use that approach with memoise one for any kind of proxying props to state calculations.

Our code looks this way

// ./decorators/memoized.js  
import memoizeOne from 'memoize-one';

export function memoized(target, key, descriptor) {
  descriptor.value = memoizeOne(descriptor.value);
  return descriptor;
}

// ./components/exampleComponent.js
import React from 'react';
import { memoized } from 'src/decorators';

class ExampleComponent extends React.Component {
  buildValuesFromProps() {
    const {
      watchedProp1,
      watchedProp2,
      watchedProp3,
      watchedProp4,
      watchedProp5,
    } = this.props
    return {
      value1: buildValue1(watchedProp1, watchedProp2),
      value2: buildValue2(watchedProp1, watchedProp3, watchedProp5),
      value3: buildValue3(watchedProp3, watchedProp4, watchedProp5),
    }
  }

  @memoized
  buildValue1(watchedProp1, watchedProp2) {
    return ...;
  }

  @memoized
  buildValue2(watchedProp1, watchedProp3, watchedProp5) {
    return ...;
  }

  @memoized
  buildValue3(watchedProp3, watchedProp4, watchedProp5) {
    return ...;
  }

  render() {
    const {
      value1,
      value2,
      value3
    } = this.buildValuesFromProps();

    return (
      <div>
        <Component1 value={value1}>
        <Component2 value={value2}>
        <Component3 value={value3}>
      </div>
    );
  }
}

The benefits of it are that you don't need to code tons of comparison boilerplate inside getDerivedStateFromProps or componentWillReceiveProps and you can skip copy-paste initialization inside a constructor.

NOTE:

This approach is used only for proxying the props to state, in case you have some inner state logic it still needs to be handled in component lifecycles.

Solution 4 - Javascript

getDerivedStateFromProps is used whenever you want to update state before render and update with the condition of props

GetDerivedStateFromPropd updating the stats value with the help of props value

read https://www.w3schools.com/REACT/react_lifecycle.asp#:~:text=Lifecycle%20of%20Components,Mounting%2C%20Updating%2C%20and%20Unmounting.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndrewView Question on Stackoverflow
Solution 1 - JavascriptOblosysView Answer on Stackoverflow
Solution 2 - JavascriptDan AbramovView Answer on Stackoverflow
Solution 3 - JavascriptmpospelovView Answer on Stackoverflow
Solution 4 - JavascriptSouMitya chauhanView Answer on Stackoverflow