Hint
Update the UI immediately before the server confirms — rollback on error; use onMutate to snapshot, onError to restore, onSettled to invalidate
Optimistic updating means updating the UI instantly when a user takes an action, without waiting for the server response. If the server returns an error, the UI rolls back.
Why it matters: eliminates perceived latency for common mutations (liking a post, toggling a checkbox, re-ordering a list).
const mutation = useMutation({
mutationFn: (newTodo) => api.addTodo(newTodo),
onMutate: async (newTodo) => {
// 1. Cancel any in-flight refetches (avoid overwriting optimistic update)
await queryClient.cancelQueries({ queryKey: ['todos'] });
// 2. Snapshot the current value for rollback
const previousTodos = queryClient.getQueryData(['todos']);
// 3. Optimistically update the cache
queryClient.setQueryData(['todos'], (old) => [...old, newTodo]);
return { previousTodos }; // context passed to onError
},
onError: (err, newTodo, context) => {
// 4. Rollback on error
queryClient.setQueryData(['todos'], context.previousTodos);
},
onSettled: () => {
// 5. Always refetch to sync with server truth
queryClient.invalidateQueries({ queryKey: ['todos'] });
},
});