Home > OS >  When can you rely on the value of this.state in react?
When can you rely on the value of this.state in react?

Time:07-01

I'm new to React, going through the tutorial on the React website. In the step by step tutorial, there is a section which explains that you should not rely on the value of state for calculating the next state, because state updates are asynchronous. Instead, they explain, you should use a version of setState that accepts a function to which the previous state is passed as an argument.

However, in the practical tutorial, the following code appears:

handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }

in which the setState call passes an object that relies on a value from this.state. Why is this code ok and why would one not have to worry about asynchronous setState execution in this case? I'm trying to understand when exactly I can rely directly on the value of this.state in my React code.

Thanks in advance!

CodePudding user response:

The tutorial's explanation is wrong. There are many cases in which you can rely on referencing this.state directly, including the case in the code snippet.

Referencing this.state directly is a problem only if

  • You have previously called this.setState with the component, and
  • The component hasn't rerendered yet, and
  • You want to call this.setState again, while taking into account the value that was just set

If any of the above conditions are false, it's just fine to set the state by referencing this.state without using the callback version.

For example, in the snippet in your question, I'd presume that handleClick is a click handler, and no other click handlers run - a different state setter does not get called before you call this.setState({ squares ..., so there's no problem.

It would be problematic if you called multiple handleClicks in sequence, though. For example, if you had something like

handleMultipleClicks() {
  for (let i = 0; i < 5; i  ) {
    handleClick(i);
  }
}

The above would be a problem, because you're calling this.setState multiple times before giving the component a chance to re-render; the this.state.squares that gets referenced in the second (and further) iterations of the loop would not reflect the value passed to this.setState in the first iteration of the loop.

One way to think of it is: this.state will reference the state at the end of the last re-render. If you write your code with that in mind, you'll be able to reliably determine whether you need to use the callback version of the state setter or not.

CodePudding user response:

In your example, you are not using the state immediately after setState hence it works as expected. Consider this example where you can get some unexpected results due to asynchronous state updates.

handleClick(i) {
  console.log(this.state.value); // 1, can be any value
  this.setState({
    value: this.state.value   1
  });
  console.log(this.state.value); // This is still 1, or the prev value
}

Also, it seems like you are using Class components so the tutorials might be very old. I would also suggest you learn functional components and hooks. It will make your life easier :)

  • Related