State Batching
Overview
When you call a state setter function (like `setCount`), React doesn't immediately stop everything and re-render the screen. That would be slow. Instead, React 'batches' multiple state updates together and performs a single re-render. Understanding that state updates are ASYNCHRONOUS is a critical milestone for a React developer.
Syntax
The `score` variable is constant during the current render. Calling `setScore` schedules an update for the *next* render. It does not change the `score` variable on the very next line.
function BatchingExample() {
const [score, setScore] = useState(0);
const handlePlay = () => {
setScore(score + 1);
// ❌ Will this print the NEW score?
// NO! It will print 0. State hasn't updated yet!
console.log("Current Score is:", score);
};
return <button onClick={handlePlay}>Play</button>;
}Since React 18, React automatically batches state updates even if they happen inside promises, setTimeout, or native event handlers. This results in massive performance boosts.
function MultipleUpdates() {
const [clicks, setClicks] = useState(0);
const [isActive, setIsActive] = useState(false);
const triggerBoth = () => {
// Both of these updates are grouped together!
// React will only re-render the component ONCE, not twice.
setClicks(prev => prev + 1);
setIsActive(true);
};
}Common Pitfalls
- Trying to use the new state value on the line immediately following the setter function.
- Forgetting to use functional updates (`prev => prev + 1`) when updating state multiple times synchronously.
Interview Tips
- If you need to execute code *after* the state has truly updated, you must use the `useEffect` hook, listening to that state variable.
Real-World Example
Batching prevents the UI from stuttering when multiple independent state variables are updated simultaneously.
function FetchDataBtn() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const fetchData = async () => {
setLoading(true); // Triggers render 1
const res = await api.get();
// In React 18, these two are batched into render 2
setData(res);
setLoading(false);
};
}