1

So just learned that componentWillReceiveProps is deprecated and we need to use getDerivedStateFromProps lifecycle method now. https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

I'm using it as such below:

class Main extends Component {
  static getDerivedStateFromProps(props) {
    console.log('getDerivedStateFromProps', props);
    const { modal } = props;
    this.setState({ modal });
  }

  constructor(props) {
    super(props);

    this.state = {
      modal: {}
    };
  }

However it errors out on the setState

enter image description here

main.js:30 Uncaught TypeError: Cannot read property 'setState' of null at getDerivedStateFromProps (main.js:30)

What am I missing here?

Leon Gaban
  • 36,509
  • 115
  • 332
  • 529
  • You might be able to use `componentWillMount` to check if there's a modal prop. If there is, set the state with it before it mounts. Rusty on react but I know using `componentDidMount` will throw an infinite loop. – Eddie D May 31 '18 at 20:57

3 Answers3

13

Because getDerivedStateFromProps is a static function, there is no instance (this).

Instead, this function is designed so that you return your state rather than using this.setState.

static getDerivedStateFromProps(props) {
    console.log('getDerivedStateFromProps', props);
    const { modal } = props;
    return { modal };
  }
Jamie Dixon
  • 53,019
  • 19
  • 125
  • 162
  • Thanks! Yeah this was it, ok new bug... for some reason my Redux action/reducers aren't forcing this new method to fire. May post a new question about that later. – Leon Gaban May 31 '18 at 21:08
  • So, how can I access `this` in `static getDerivedStateFromProps()`? – 5ervant - techintel.github.io Jun 19 '18 at 12:05
  • 1
    I think it's important to note **an implementation like this is unnecessary**. Please see [my answer](https://stackoverflow.com/a/50784891/458193) for more details. (I work on React.) – Dan Abramov Jun 19 '18 at 13:31
7

Aside from the mistake that was already pointed out (you need to return state), your implementation is buggy and won't work correctly.

You are trying to "sync" a prop into the local state. This is a bad idea because any unrelated re-render of a parent component will destroy local state.

It looks like you should completely remove getDerivedStateFromProps, and just use props directly. You don't need local state in this example at all.

For a more in-depth take on why this pattern is broken, and some easy alternatives to it, check out the official React blog post on avoiding deriving state.

Dan Abramov
  • 264,556
  • 84
  • 409
  • 511
  • Thanks for the reply Dan! I'm honored :D And ok yeah I just removed that from my app, and yeah everything is working just from `this.props` so I guess the use case for `getDerivedStateFromProps` are some rare edge cases? – Leon Gaban Jun 11 '18 at 16:26
  • 1
    Yes, it's for rare cases when your state depends on a *change* in props. For example, `isScrollingDown` might depend on change in `scrollPosition`. – Dan Abramov Jun 19 '18 at 13:30
1

You're using this in the context of a static method. Static does not rely on an instance of the class, so the this isn't the same. You're best bet is to return modal in a non static method and then set it from there :D

class Main extends Component {
  static getDerivedStateFromProps(props) {
    console.log('getDerivedStateFromProps', props);
    const { modal } = props;
    return modal;
  }

  constructor(props) {
    super(props);

    this.state = {
      modal: {}
    };
    
    SetModalState(modal)
    {
      this.setState(modal)
    }
  }
Eddie D
  • 1,120
  • 7
  • 16