Performance: Optimistic state updates
Optimistic state updates improve user interaction speed by showing UI changes immediately before server confirmation, impacting input responsiveness and perceived performance.
function handleClick() { const oldState = state; setState(newState); // update UI immediately fetch('/api/update', { method: 'POST' }) .then(response => { if (!response.ok) { setState(oldState); // rollback on server error throw new Error(); } }) .catch(() => { setState(oldState); // rollback on network error }); }
async function handleClick() { const response = await fetch('/api/update', { method: 'POST' }); if (response.ok) { setState(newState); } }
| Pattern | DOM Operations | Reflows | Paint Cost | Verdict |
|---|---|---|---|---|
| Wait for server response before UI update | Minimal until response | 1 reflow after response | 1 paint after response | [X] Bad |
| Optimistic UI update with rollback on failure | Immediate DOM update | 1 reflow on update, possible 1 reflow on rollback | 1 paint per update/rollback | [OK] Good |
useState in Next.js?const [count, setCount] = useState(0);
async function increment() {
setCount(count + 1); // optimistic update
try {
await fetch('/api/increment', { method: 'POST' });
} catch {
setCount(count); // revert on failure
}
}count if the server request fails?const [items, setItems] = useState([]);
async function addItem(newItem) {
setItems([...items, newItem]);
try {
await fetch('/api/add', { method: 'POST', body: JSON.stringify(newItem) });
} catch {
// What is missing here?
}
}items to previous state if fetch fails.items state to previous value in catch -> Option BPass the test and this pattern moves unknown