Optimistic Updates — Complete Guide
Optimistic Updates — Complete Guide: free step-by-step lesson with examples, common mistakes, and interview tips — part of React.js Tutorial on Toolliyo Academy.
On this page
React.js Tutorial · Lesson 46 of 100
Optimistic Updates
Beginner ✓ → Intermediate → Advanced → Professional
Intermediate · 2 — Build apps · ~14 min read · Module 5: State & Authentication
Introduction
You know the basics now. Here we use Optimistic Updates in real app situations — forms, pages, and data. Still plain language, just a bit more depth. Optimistic updates change the UI immediately before the server confirms. If the request fails, you roll back to the previous state. Apps feel instant — like when you "like" a post and the heart fills before the network finishes.
State mistakes cause the most React bugs for beginners. Keep server data and UI state separate — this lesson shows how teams do that.
When will you use this?
Use these patterns when data is shared across pages or comes from a server.
- Shopping carts, user sessions, and API data need clear state patterns.
- Teams pick Context, Zustand, or Redux based on app size — you will see all three in jobs.
Real-world: chat message appears instantly
Freshdesk agent reply shows in thread immediately while API saves — rolled back if server returns 500.
Production-style code
const mutation = useMutation({
mutationFn: sendReply,
onMutate: async newReply => {
await queryClient.cancelQueries(['ticket', ticketId]);
const prev = queryClient.getQueryData(['ticket', ticketId]);
queryClient.setQueryData(['ticket', ticketId], old => ({
...old,
messages: [...old.messages, { ...newReply, pending: true }]
}));
return { prev };
},
onError: (_err, _vars, ctx) => {
queryClient.setQueryData(['ticket', ticketId], ctx.prev);
}
});
What happens in production: Apps feel instant like WhatsApp — users tolerate slow networks when UI responds immediately.
Lesson example (start here)
Copy this smaller example first. Once it works, compare it with the real-world code above.
const mutation = useMutation({
mutationFn: updateTodo,
onMutate: async newTodo => {
await queryClient.cancelQueries(['todos']);
const previous = queryClient.getQueryData(['todos']);
queryClient.setQueryData(['todos'], old => [...old, newTodo]);
return { previous };
},
onError: (err, vars, ctx) => {
queryClient.setQueryData(['todos'], ctx.previous);
}
});
Line-by-line walkthrough
| Code | What it means |
|---|---|
const mutation = useMutation({ | TanStack Query hook — loads or updates server data with caching built in. |
mutationFn: updateTodo, | Part of the Optimistic Updates example — read it together with the lines before and after. |
onMutate: async newTodo => { | Defines a function — often a component or event handler. |
await queryClient.cancelQueries(['todos']); | Part of the Optimistic Updates example — read it together with the lines before and after. |
const previous = queryClient.getQueryData(['todos']); | Part of the Optimistic Updates example — read it together with the lines before and after. |
queryClient.setQueryData(['todos'], old => [...old, newTodo]); | Defines a function — often a component or event handler. |
return { previous }; | Sends UI or a value back to whoever called this function. |
}, | Closes a block started by { or ( above. |
onError: (err, vars, ctx) => { | Defines a function — often a component or event handler. |
queryClient.setQueryData(['todos'], ctx.previous); | Part of the Optimistic Updates example — read it together with the lines before and after. |
} | Closes a block started by { or ( above. |
}); | Closes a block started by { or ( above. |
How it works (big picture)
- onMutate updates cache immediately and saves previous data.
- onError restores it if the API fails.
Do this on your computer
- Use useMutation from TanStack Query.
- build onMutate to patch cache.
- Rollback in onError.
- Read the real-world section and name which part of the app uses this topic.
- Run the example locally and confirm the same behavior in the browser.
- Change one value in the example (text, initial state, or URL) and predict what will happen before you save.
Experiments — try changing this
- Change text or labels in the example and save — watch the browser update.
- Break the code on purpose (remove a bracket), read the error message, then fix it.
- Open React DevTools (browser extension) while running Optimistic Updates and inspect component props/state.
Remember
Update UI first, sync with server second. Always handle failure rollback. Great for likes, toggles, list adds.
Common questions
When not to use?
Money transfers, irreversible deletes — wait for server OK.
How long should I spend on Optimistic Updates?
Until you can explain it in your own words and run the example without looking at the answer. Beginners often need 30–60 minutes per new hook or routing topic; setup lessons may take one afternoon.
What if I get stuck on Optimistic Updates?
Re-read the line-by-line walkthrough, check the browser console for red errors, and compare your code character-by-character with the example. Search the exact error text — someone else had it too.
Where is Optimistic Updates used in real jobs?
See the real-world section above — the same pattern appears in LMS, banking, e-commerce, and SaaS products. Interviewers ask you to explain it using one concrete example from your project or this lesson.
Sign in to ask a question or upvote helpful answers.
No questions yet — be the first to ask!