Skip to main content
Optimistic updates allow you to update the UI immediately when a user performs an action, before the server responds. This creates a snappy, responsive user experience.

Basic Pattern

Optimistic updates are implemented using the onMutate callback in mutations:

The Three Callbacks

onMutate

Runs before the mutation function. Use it to:
  1. Cancel outgoing queries
  2. Snapshot current data
  3. Optimistically update the cache
  4. Return context for rollback

onError

Runs if the mutation fails. Use the context to rollback:

onSettled

Runs after mutation completes (success or error). Refetch to sync with server:
Always invalidate in onSettled rather than onSuccess to ensure data is refreshed even after rollbacks.

Complete Example: Update Todo

Delete with Optimistic Update

Using queryOptions for Type Safety

Get better TypeScript support with queryOptions:

Updating Multiple Queries

Optimistically update related queries:

UI Feedback During Mutations

Show optimistic state in the UI:

Retry on Error

Show retry UI for failed optimistic updates:

Optimistic Updates with Infinite Queries

Update infinite query pages:
Always call cancelQueries before optimistic updates to prevent race conditions where a slow query overwrites your optimistic update.

Best Practices

  1. Always snapshot previous data in onMutate for rollback
  2. Cancel queries before optimistic updates to avoid race conditions
  3. Use onSettled for invalidation, not onSuccess (handles both success and error)
  4. Show visual feedback when mutations are pending
  5. Provide retry mechanisms for failed updates
  6. Test error scenarios thoroughly

Next Steps