Passing a function to setState
Here’s the dirty secret about setState — it’s actually asynchronous. React batches state changes for performance reasons, so the state may not change immediately after setState is called. That means you should not rely on the current state when calling setState — since you can’t be sure what that state will be! Here’s the solution — pass a function to setState, with the previous state as an argument. Doing so avoids issues with the user getting the old state value on access (due to the asynchrony of setState)
Problem
// assuming this.state.count === 0
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
// this.state.count === 1, not 3
Solution
this.setState((prevState, props) => ({
count: prevState.count + props.increment
}));
Variations
// Passing object
this.setState({ expanded: !this.state.expanded });
// Passing function
this.setState(prevState => ({ expanded: !prevState.expanded }));