0

Lets say I have a state that I would like to update:

state = {
  description: "",
  notes: ""
}

Is there a difference if I update the state with just an object, if I do not need to use prevState?

this.setState({description: "Blue"});

vs

this.setState((prevState)=> ({description: "Blue"}));
Kalhan.Toress
  • 21,683
  • 8
  • 68
  • 92
Brian Bui
  • 103
  • 1
  • 6
  • 5
    Your second version should be `()=> ({description: "Blue"})` – Nick Parsons Jun 25 '20 at 03:38
  • 1
    Take a look at this [Stackoverflow post](https://stackoverflow.com/questions/42038590/when-to-use-react-setstate-callback) – itsanewabstract Jun 25 '20 at 03:38
  • 1
    To add to @NickParsons comment. You must include `() => ({description: "Blue"})` because your returning a object literal. – Tanner Dolby Jun 25 '20 at 03:41
  • 1
    There is no difference. Second form of `this.setState` that takes a callback function, only exists to allow updating the state based on previous state. – Yousaf Jun 25 '20 at 03:41
  • Wait, now Im confused.Since I am not updating the function multiple times, I dont need to wait for anything to update for me to use a callback right? So I can just use this.setState({description: "Blue"}); – Brian Bui Jun 25 '20 at 03:45
  • 2
    if you don't need previous state to update the state, use `this.setState({description: "Blue"});` – Yousaf Jun 25 '20 at 03:48
  • @Yousaf Okay thank you. I got confused by the other answers. – Brian Bui Jun 25 '20 at 03:49
  • @BrianBui `this.setState(nextState)` vs `this.setState((prevState, props) => nextState)` vs `this.setState(nextState, callbackCalledAfterStateIsSet)` – thammada.ts Jun 25 '20 at 03:54

1 Answers1

3

I've created the demo to visualize the difference

/* When we doing this state gets update after the for loops runs so,
 this.state.count is same for each repeat so even if we expecting to 
count increase by 5 its actually increment by 1 */
updateCountByFive = () => {
  for (let a = 0; a < 5; a++) {
    this.setState({
      count: this.state.count + 1
    });
  }
};

/* In this case by using callback to set the new state,
react is smart enough to pass the latest count value to the callback 
event if that new change not rendered */
updateCountByFiveCallback = () => {
  for (let a = 0; a < 5; a++) {
    this.setState(prevState => {
      return {
        count: prevState.count + 1
      };
    });
  }
};

So it's a good practice to use callback version when you need to use current state to set the next state, since it will prevent some issues as above

This is what react doc says.

React may batch multiple setState() calls into a single update for performance.

Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.

there is a nice article here

yurylavrukhin
  • 42
  • 1
  • 6
Kalhan.Toress
  • 21,683
  • 8
  • 68
  • 92
  • Thanks for the further explanation! I understood why I should use a callback in I want to update something depending on the previous state. I was just curious if I could pass in an object and no call back if my updates are not dependent of the previous state. – Brian Bui Jun 25 '20 at 05:01
  • 1
    Yup, That's Correct, I have updated the answer with react docs have a look on it, It says `Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.` – Kalhan.Toress Jun 25 '20 at 05:03