Skip to main content
Mutations are used to create, update, or delete data on your server. Unlike queries, mutations are typically used to modify server state and trigger side effects.

Mutation Basics

A mutation is created using the useMutation hook:

Mutation States

A mutation can be in one of the following states:

Status States

  • idle - The mutation is idle or fresh/reset
  • pending - The mutation is currently running
  • error - The mutation encountered an error
  • success - The mutation was successful
From mutation.ts:26-41, the mutation state structure is:

Derived Boolean States

The mutation result includes convenient boolean flags derived from mutationObserver.ts:145-159:

Mutation Functions

mutate

The mutate function is used to trigger the mutation. It’s fire-and-forget - errors are not thrown but passed to callbacks:

mutateAsync

The mutateAsync function returns a Promise, allowing you to use async/await:
mutate calls the callbacks you pass to it, while mutateAsync doesn’t. If you need callbacks, use mutate. If you need the Promise behavior, use mutateAsync.

Side Effects

Mutations support several lifecycle callbacks for performing side effects:

onMutate

Called before the mutation function is fired. Useful for optimistic updates:

onSuccess

Called when the mutation succeeds:

onError

Called when the mutation encounters an error:

onSettled

Called when the mutation finishes, regardless of success or failure:

Callback Execution Order

Callbacks are executed in the following order, as implemented in mutationObserver.ts:161-219:
  1. onMutate (before the mutation function)
  2. Mutation function executes
  3. Either:
    • onSuccessonSettled (on success)
    • onErroronSettled (on error)

Mutation Context

The mutation function context provides metadata about the mutation:
This context is passed to all callbacks, allowing you to access the QueryClient, metadata, and mutation key.

Resetting Mutations

You can reset a mutation back to its idle state:
From mutationObserver.ts:119-126:

Retry Behavior

Unlike queries, mutations do not retry by default. You can configure retry behavior:

Persisting Mutations

Mutations can be persisted to storage and resumed later, useful for offline-first applications:
Use the resumePausedMutations method on the QueryClient to resume paused mutations when the app comes back online.

Optimistic Updates

Optimistic updates allow you to update the UI before the mutation completes:

Mutation Scope

Each call to mutate creates a new mutation execution. The mutation state represents the most recent execution:
The mutation observer always tracks the latest mutation execution. Previous executions are not stored in the observer state.

Type Safety

Mutations are fully type-safe:

Global Mutation Callbacks

You can set up global mutation callbacks in the MutationCache: