Optimistic Update
Problem
UI freezes or shows spinners after every user action, waiting for server confirmation. Simple interactions like liking a post, adding to cart, or marking items complete feel sluggish and unresponsive. Users perceive the app as slow even when the network is fast.
Solution
Update the UI immediately assuming operations will succeed, then rollback if they fail. This creates responsive interfaces that feel instant while handling errors gracefully.
Example
This example shows optimistic updates where the UI is immediately updated before the server responds, with automatic rollback if the operation fails.
const { mutate } = useMutation(updateTodo, {
onMutate: async (newTodo) => {
// Immediately update the UI before server responds
// User sees instant feedback without waiting
queryClient.setQueryData('todos', (old) => [...old, newTodo]);
},
onError: (err, newTodo, context) => {
// If server rejects, rollback to previous state
queryClient.setQueryData('todos', context.previousTodos);
}
});
Benefits
- Makes interactions feel instant by not waiting for server confirmation.
- Dramatically improves perceived performance and user satisfaction.
- Reduces visual friction from loading spinners and disabled buttons.
- Creates responsive interfaces that match user expectations for speed.
Tradeoffs
- Adds complexity with rollback logic when operations fail.
- Can confuse users if optimistic updates are rolled back frequently.
- Requires careful state management to handle conflicts and race conditions.
- May show incorrect data temporarily if the server rejects the operation.