Mutation
Problem
Creating, updating, or deleting data leaves the UI showing stale information until a manual refresh. Users add items to a list but don’t see them appear, edit records but still see old values, or delete items that remain visible. The displayed data becomes out of sync with the server, forcing users to refresh the page to see their changes take effect.
Solution
Declare operations that modify server state, handling optimistic updates and cache invalidation. This provides structure for create, update, and delete operations with error handling and loading states.
Example
This example demonstrates using a mutation to create a new todo item, automatically invalidating the cached todos list to keep the UI synchronized with the server.
// Define mutation for creating a new todo
const { mutate, isLoading } = useMutation(
(newTodo) => fetch('/api/todos', {
method: 'POST',
body: JSON.stringify(newTodo)
}),
{
// After successful creation, invalidate cached todos
// This triggers a refetch to get the updated list
onSuccess: () => queryClient.invalidateQueries('todos')
}
);
// Trigger the mutation to create a new todo
mutate({ title: 'New task' });
Benefits
- Keeps UI in sync with server by automatically refreshing after mutations.
- Provides structured handling for loading and error states during modifications.
- Enables optimistic updates for instant perceived performance.
- Centralizes cache invalidation logic to prevent stale data.
Tradeoffs
- Adds complexity with cache management and invalidation strategies.
- Can cause race conditions if multiple mutations affect the same data.
- Requires careful error handling to roll back optimistic updates on failure.
- May over-fetch data if cache invalidation is too aggressive.