Usually I see this kind of state update (this is just an example):
const NumArray = () => {
const [numbers, setNumbers] = useState([])
return (
<div>
<p>Numbers:[ {numbers} ]</p>
/////////////////////
<button onClick={() => setNumbers(prevState => [...prevState, 1])}>
/////////////////////
Click me
</button>
</div>
)
}
But if i use this variation it still works:
const NumArray = () => {
const [numbers, setNumbers] = useState([])
return (
<div>
<p>Numbers:[ {numbers} ]</p>
/////////////////////
<button onClick={() => setNumbers([...numbers, 1])}>
/////////////////////
Click me
</button>
</div>
)
}
My question is, what is the difference between the two state updates? Why do people tend to use the one with the callback?
useState is asynchronous. It does not update the state immediately but have queue that is used to update the state object. This is done to improve the performance of the rendering of React components.
Even though it is asynchronous, useState function does not return promise. Therefore we cannot attach a then handler to it or use async/await to get the updated state values. And if we have some state variables that need to be updated according to another state variable, we cannot rely on the updated state variable synchronously.
The state update usually happens on the next render, but even that can vary. Batching updates is up to react, and there is nothing we can do to change that.
So writing it like this:
<button onClick={() => setNumbers(prevState => [...prevState, 1])}>
guaranties that prevState is actually previous state. While when writing it without callback we don't care a lot if it is exact previous state or not.