gotchajavascriptreactModeratepending
Gotcha: React state updates are batched (and sometimes not)
Viewed 0 times
batchingsetStateflushSyncre-renderasync-state
Error Messages
Problem
Multiple setState calls sometimes trigger one re-render (batched) and sometimes trigger multiple re-renders, depending on the context.
Solution
React 18+ batches all state updates automatically:
// React 18: ALL updates are batched (one re-render)
function handleClick() {
setCount(c => c + 1); // Batched
setFlag(f => !f); // Batched
// Only ONE re-render
}
// Even in async code (NEW in React 18):
async function handleSubmit() {
const data = await fetchData();
setData(data); // Batched
setLoading(false); // Batched
// Only ONE re-render
}
// setTimeout too:
setTimeout(() => {
setCount(c => c + 1); // Batched in React 18
setFlag(f => !f); // Batched in React 18
}, 1000);
// If you NEED immediate re-render (rare):
import { flushSync } from 'react-dom';
flushSync(() => {
setCount(c => c + 1);
});
// DOM is updated here
setFlag(f => !f);
// Common gotcha: reading state after setting it
setCount(count + 1);
console.log(count); // Still old value!
// Fix: use functional update or useEffect
setCount(prev => {
const newCount = prev + 1;
console.log(newCount); // New value
return newCount;
});
// React 18: ALL updates are batched (one re-render)
function handleClick() {
setCount(c => c + 1); // Batched
setFlag(f => !f); // Batched
// Only ONE re-render
}
// Even in async code (NEW in React 18):
async function handleSubmit() {
const data = await fetchData();
setData(data); // Batched
setLoading(false); // Batched
// Only ONE re-render
}
// setTimeout too:
setTimeout(() => {
setCount(c => c + 1); // Batched in React 18
setFlag(f => !f); // Batched in React 18
}, 1000);
// If you NEED immediate re-render (rare):
import { flushSync } from 'react-dom';
flushSync(() => {
setCount(c => c + 1);
});
// DOM is updated here
setFlag(f => !f);
// Common gotcha: reading state after setting it
setCount(count + 1);
console.log(count); // Still old value!
// Fix: use functional update or useEffect
setCount(prev => {
const newCount = prev + 1;
console.log(newCount); // New value
return newCount;
});
Why
React 18 introduced automatic batching for all updates. In React 17 and below, only event handler updates were batched.
Revisions (0)
No revisions yet.