0

Please, help to understand the essence of how React setState actually works. Here is example:

  class App extends React.Component { // first example

  state = {
    clicks: 0
  };

  handleButtonClick = this.handleButtonClick.bind(this);

  handleButtonClick() {
    this.setState({ // like this? Or should we use callback instead of object?
      clicks: this.state.clicks + 1
    });
  }

  render() {
    return (
      <div>
        <div>Count: {this.state.clicks}</div>
        <button onClick={this.handleButtonClick}>Click</button>
      </div>
    );
  }

}

if we call setstate multiple times, we should use callback:

this.setState(prevState => ({ // second example
  clicks: prevState.clicks + 1
}));
this.setState(prevState => ({
  clicks: prevState.clicks + 1
}));

and calls will be like: setState then setState. But in first example we have one call setState: Click then setState then click then setState.

You see? In first example we have CLICK between setState. In second example we does not have click, we have immediately call one by one.

Question: Should we use callback instead of object? Why? Now all work properly.

I searched for the answer on the Internet for a long time but did not find good arguments on this case.

P.S. sorry for my bad English.

kind user
  • 40,029
  • 7
  • 67
  • 77
  • 1
    Does this answer your question? [When to use React setState callback](https://stackoverflow.com/questions/42038590/when-to-use-react-setstate-callback) – Jay Nov 27 '19 at 12:41

2 Answers2

1

I think what you mean by callback is actually referred to as functional form of setState.

To answer your question, general rule of thumb is - if the next value of state depends on its previous value - use the functional form of setState.

The reason why is that because when you call this.setState({ clicks: this.state.clicks + 1 }); several times in a row, React batches those calls to avoid unnecessary reconciliation operations. So, for example when you call setState like that 3 times, you'd expect the final value of the clicks to be 3, but it will be 1, because all the updates were batched and used the initial value of 0 to calculate the next state.

On the other hand, when you use functional form of setState, the updates to the state are queued, so they will be executed one after another, using previous value of the state.

Here's a quite in-depth explanation.

Clarity
  • 10,730
  • 2
  • 25
  • 35
0

Multiple things here:

  1. You should be using constructor in your component in which your state and all the bindings live. Like this:
class App extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      clicks: 0
    }
    this.handleButtonClick = this.handleButtonClick.bind(this);
  }

  //rest of our component here....
}
  1. setState is an asynchronous operation so if you want something to happen only after setting your state then you have to use callback in setState, but in your case you are using the function as a click handler. React takes care of this automatically and you dont have to worry about the multiple button clicks. It will always register the click and increment the click count correctly.
Harshit Agarwal
  • 2,308
  • 2
  • 15
  • 23