Reputation: 4333
Here's the working example in CodePen.
It has a button which toggles between ON
and OFF
In React docs, it used prevState
and updated the value of state.
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
It also produces the same result when I use the below method.
this.setState({isToggleOn: !this.state.isToggleOn})
Could anyone suggest which one is good way and is recommended way to update the State the Component
?
Upvotes: 2
Views: 106
Reputation: 59501
Like others said, you should do like you did in your first example.
It's rare that prevState => ({isToggleOn: !prevState.isToggleOn})
will yield a different result than that of {isToggleOn: !this.state.isToggleOn}
, but it can happen.
It's generally recommended to always use the updater function whenever you are setting a new state that depends on the value of the old state.
Here are two snippets that demonstrate what can happen:
setState
Here, despite increasing the counter twice with setState
it only increments by 1 each time.
class App extends React.Component {
constructor() {
super();
this.state = {counter: 0};
this.increment = this.increment.bind(this);
}
increment() {
this.setState({counter: this.state.counter + 1});
this.setState({counter: this.state.counter + 1});
}
render() {
return (
<div>
<h3>{this.state.counter}</h3>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
setState
Here, the counter increments correctly by 2.
class App extends React.Component {
constructor() {
super();
this.state = {counter: 0};
this.increment = this.increment.bind(this);
}
increment() {
this.setState(prevState => ({counter: prevState.counter + 1}));
this.setState(prevState => ({counter: prevState.counter + 1}));
}
render() {
return (
<div>
<h3>{this.state.counter}</h3>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Upvotes: 1
Reputation: 1514
Because of to the asynchronous nature of setState
, it is not advisable to use this.state
to get the previous state within a setState
. Instead, if you have to use the previous state, rely on the updater function approach.
Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately. https://reactjs.org/docs/react-component.html#setstate
Upvotes: 3