Optimistic Updates
Optimistic updates are a powerful technique that can make your applications feel faster and more responsive. When you use optimistic updates, you immediately update the UI as if a mutation—such as editing or deleting an item—has already succeeded, even before you receive a response from the server. This approach gives users instant feedback, reducing perceived latency and making the interface feel snappier.
To implement optimistic updates in React Query, you use the useMutation hook along with its lifecycle callbacks. The most important callbacks for optimistic updates are onMutate, onError, and onSettled. The onMutate callback is triggered before the mutation function runs. Here, you can update the cache to reflect the anticipated change. If the mutation fails, the onError callback lets you roll back the cache to its previous state. Finally, onSettled ensures that your cache stays in sync with the server by refetching or updating the relevant queries.
Suppose you have a todo list and want to let users mark a todo as completed. With optimistic updates, you update the todo's status in the UI as soon as the user clicks, without waiting for the server. If the server later reports an error, you revert the change.
Here is a step-by-step example of an optimistic update flow:
- When a user marks a todo as completed, you trigger a mutation using
useMutation; - In the
onMutatecallback, you update the cached todo list so the UI reflects the change immediately; - If the mutation fails, the
onErrorcallback restores the previous cache state, rolling back the UI; - Once the server responds (success or failure), the
onSettledcallback ensures the cache is up to date.
import { useMutation, useQueryClient } from '@tanstack/react-query';
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: updateTodoOnServer,
// Optimistically update the cache before the mutation function runs
onMutate: async (updatedTodo) => {
await queryClient.cancelQueries({ queryKey: ['todos'] });
const previousTodos = queryClient.getQueryData(['todos']);
queryClient.setQueryData(['todos'], (old = []) =>
old.map((todo) =>
todo.id === updatedTodo.id
? { ...todo, completed: updatedTodo.completed }
: todo
)
);
return { previousTodos };
},
// Roll back the cache if the mutation fails
onError: (error, updatedTodo, context) => {
if (context?.previousTodos) {
queryClient.setQueryData(['todos'], context.previousTodos);
}
},
// Ensure the cache stays in sync with the server
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['todos'] });
},
});
With this setup, users see the todo marked as completed right away. If the server rejects the update, the UI reverts to its previous state, maintaining consistency between the client and the server.
Tack för dina kommentarer!
Fråga AI
Fråga AI
Fråga vad du vill eller prova någon av de föreslagna frågorna för att starta vårt samtal
Can you explain what happens if the server returns an error during an optimistic update?
How do I handle multiple simultaneous optimistic updates in React Query?
Can you show how to use optimistic updates for deleting an item instead of updating?
Fantastiskt!
Completion betyg förbättrat till 7.14
Optimistic Updates
Svep för att visa menyn
Optimistic updates are a powerful technique that can make your applications feel faster and more responsive. When you use optimistic updates, you immediately update the UI as if a mutation—such as editing or deleting an item—has already succeeded, even before you receive a response from the server. This approach gives users instant feedback, reducing perceived latency and making the interface feel snappier.
To implement optimistic updates in React Query, you use the useMutation hook along with its lifecycle callbacks. The most important callbacks for optimistic updates are onMutate, onError, and onSettled. The onMutate callback is triggered before the mutation function runs. Here, you can update the cache to reflect the anticipated change. If the mutation fails, the onError callback lets you roll back the cache to its previous state. Finally, onSettled ensures that your cache stays in sync with the server by refetching or updating the relevant queries.
Suppose you have a todo list and want to let users mark a todo as completed. With optimistic updates, you update the todo's status in the UI as soon as the user clicks, without waiting for the server. If the server later reports an error, you revert the change.
Here is a step-by-step example of an optimistic update flow:
- When a user marks a todo as completed, you trigger a mutation using
useMutation; - In the
onMutatecallback, you update the cached todo list so the UI reflects the change immediately; - If the mutation fails, the
onErrorcallback restores the previous cache state, rolling back the UI; - Once the server responds (success or failure), the
onSettledcallback ensures the cache is up to date.
import { useMutation, useQueryClient } from '@tanstack/react-query';
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: updateTodoOnServer,
// Optimistically update the cache before the mutation function runs
onMutate: async (updatedTodo) => {
await queryClient.cancelQueries({ queryKey: ['todos'] });
const previousTodos = queryClient.getQueryData(['todos']);
queryClient.setQueryData(['todos'], (old = []) =>
old.map((todo) =>
todo.id === updatedTodo.id
? { ...todo, completed: updatedTodo.completed }
: todo
)
);
return { previousTodos };
},
// Roll back the cache if the mutation fails
onError: (error, updatedTodo, context) => {
if (context?.previousTodos) {
queryClient.setQueryData(['todos'], context.previousTodos);
}
},
// Ensure the cache stays in sync with the server
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['todos'] });
},
});
With this setup, users see the todo marked as completed right away. If the server rejects the update, the UI reverts to its previous state, maintaining consistency between the client and the server.
Tack för dina kommentarer!