How do I ensure that I read the most recent version of the report?

advertisements

I may be missing something. I know setState is asynchronous in React, but I still seem to have this question.

Imagine following is a handler when user clicks any of the buttons on my app

1. ButtonHandler()
2. {
3. if(!this.state.flag)
4. {
5.   alert("flag is false");
6. }
7. this.setState({flag:true});
8.
9. }

  • Now imagine user very quickly clicks first one button then second.
  • Imagine the first time the handler got called this.setState({flag:true}) was executed, but when second time the handler got called, the change to the state from the previous call has not been reflected yet -- and this.state.flag returned false.
  • Can such situation occur (even theoretically)? What are the ways to ensure I am reading most up to date state?
  • I know setState(function(prevState, props){..}) gives you access to previous state but what if I want to only read state like on line 3 and not set it?

As you rightly noted, for setting state based on previous state you want to use the function overload.

I know setState(function(prevState, props){..}) gives you access to previous state

So your example would look like this:

handleClick() {
  this.setState(prevState => {
    return {
      flag: !prevState.flag
    };
  });
}

what if I want to only read state like on line 3 and not set it?

Let's get back to thinking why you want to do this.

If you want to perform a side effect (e.g. log to console or start an AJAX request) then the right place to do it is the componentDidUpdate lifecycle method. And it also gives you access to the previous state:

componentDidUpdate(prevState) {
  if (!prevState.flag && this.state.flag) {
    alert('flag has changed from false to true!');
  }
  if (prevState.flag && !this.state.flag) {
    alert('flag has changed from true to false!');
  }
}

This is the intended way to use React state. You let React manage the state and don't worry about when it gets set. If you want to set state based on previous state, pass a function to setState. If you want to perform side effects based on state changes, compare previous and current state in componentDidUpdate.

Of course, as a last resort, you can keep an instance variable independent of the state.