I recently read the react.js documentation and found inconsistencies in setting the state based on previous state value. Here is that chunk of code:
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
I thought this way () => this.setState({ count: this.state.count + 1 })
of setting state
is wrong and you should use callback for that purpose instead. So I've raised the PR in which I add use of callback function with previous state and it was deprecated because
The callback version is useful when you're not certain what the captured value of state is.
I don't really like when you're not certain part of the explanation and can someone explain why do this way () => this.setState({ count: this.state.count + 1 })
of setting the state is correct.
Thanks in advance.
In your current example, where you set your default state to { count: 0 }
, you are "safe" to do setState({ count: this.state.count + 1 })
because when you first update your state, 0 + 1
will produce a valid result.
class App extends React.Component {
state = { count: 0 }
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button
onClick={() => this.setState({ count: this.state.count + 1 })}
>
Click me!
</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>
However, let's assume your initial value for some piece of state
is not 0
, so calling this.state.count + 1
could produce an invalid result. This is where you'd reach for the callback
version because:
you're not certain what the captured value of state is.
class App extends React.Component {
state = { count: null }
render() {
const handleClick = () => {
this.setState((prevState) => {
// count is initially `null`, so
// `null + 1` could yield an undesired result
if (!Number.isInteger(prevState.count)) {
return { count: 1 }
}
return { count: prevState.count + 1 }
})
}
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={handleClick}>
Click me!
</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>
This is just an example, but you get the idea.
Your PR was most likely declined because the example in the docs is correct, assuming that is used in the same context where it is "safe" to update your state by doing this.setState({ count: this.state.count + 1 })
.
Here's the documentation:
Both ways of updating state
are correct and should be used when appropriate. As you can see in the second example, the "callback option" would be a better solution if want to do some checks prior to updating your state
.
Still, the example in the documentation is correct and wouldn't produce any benefits if it was using the "callback option" instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With