State & Events
React Functional State Updates
Passing a function to a state setter — setCount(prev => prev + 1) — gives you the latest queued value rather than the snapshot captured by the current render. This is the correct form whenever the new state depends on the old.
What is Functional State Updates in React?
Passing a function to a state setter — setCount(prev => prev + 1) — gives you the latest queued value rather than the snapshot captured by the current render. This is the correct form whenever the new state depends on the old.
Why Functional State Updates matters
React batches updates. Calling setCount(count + 1) three times in one handler applies the same stale count three times, so the value goes up by one instead of three.
Functional State Updates example
// count is 0 in this render's snapshot
setCount(count + 1); // queues "set to 1"
setCount(count + 1); // queues "set to 1" again
setCount(count + 1); // result: 1
setCount(c => c + 1); // queues "add 1"
setCount(c => c + 1);
setCount(c => c + 1); // result: 3How this works
React applies the queued updaters in order, feeding each the result of the previous one. The plain-value form has no access to that chain — it only knows the value captured when the render ran.
Key points to remember
- Use the functional form whenever the next value derives from the previous one.
- It is also the fix for stale values inside setInterval, setTimeout and event listeners.
- React 18 batches updates everywhere, including inside promises and timeouts.
Common mistakes with Functional State Updates
- Incrementing inside a loop with the plain form and losing all but the last update.
- Reading state inside an interval callback registered once — it captures the first render’s value forever.
A simple rule: if the new state mentions the old state, use the function form.
React Functional State Updates— Interview Questions & FAQs
Why does my counter only increase by one when I call setCount three times?+
All three calls read the same snapshot of count from the current render. Use setCount(c => c + 1) so each update receives the result of the previous one.
