Props and state
State is a snapshot
Understand why a state variable does not change inside the event handler that has already captured the current render.
Every render receives a snapshot of props and state. The event handlers created during that render keep seeing that snapshot.
Consider three updates in one click:
function Counter() {
const [count, setCount] = useState(0)
function addThree() {
setCount(count + 1)
setCount(count + 1)
setCount(count + 1)
}
return <button onClick={addThree}>{count}</button>
}
If count is 0, every line requests setCount(0 + 1). The next render shows 1, not 3.
When the next value depends on a queued previous value, pass an updater function:
setCount(current => current + 1)
setCount(current => current + 1)
setCount(current => current + 1)
React processes the queue in order: 0 → 1 → 2 → 3.
Snapshots also explain delayed handlers:
function showLater() {
setTimeout(() => alert(count), 2000)
}
The alert sees the count from the render that created showLater, even if another render happens before the timer runs.
This behavior prevents a running handler from changing underneath you. Use an updater when calculating the next state from previous state. Use a ref only when an asynchronous callback genuinely needs the latest mutable value without rendering it.
Try both addThree versions and predict the result before clicking.
Lesson completed