Skip to main content

Mutation

The Mutation class represents a single mutation instance. It manages the lifecycle of a mutation execution, including state, retries, and callbacks.

Import

import { Mutation } from '@tanstack/query-core'

Constructor

class Mutation<
  TData = unknown,
  TError = DefaultError,
  TVariables = unknown,
  TContext = unknown,
> {
  constructor(config: MutationConfig<TData, TError, TVariables, TContext>)
}

Type Parameters

TData
type
default:"unknown"
The type of data returned by the mutation function
TError
type
default:"DefaultError"
The type of error that can be thrown
TVariables
type
default:"unknown"
The type of variables passed to the mutation function
TContext
type
default:"unknown"
The type of context returned by onMutate

Properties

state

state: MutationState<TData, TError, TVariables, TContext>
The current state of the mutation.
interface MutationState<TData, TError, TVariables, TContext> {
  context: TContext | undefined
  data: TData | undefined
  error: TError | null
  failureCount: number
  failureReason: TError | null
  isPaused: boolean
  status: 'idle' | 'pending' | 'error' | 'success'
  variables: TVariables | undefined
  submittedAt: number
}

options

options: MutationOptions<TData, TError, TVariables, TContext>
The mutation configuration options.

mutationId

mutationId: number
Unique identifier for this mutation instance.

Methods

execute

execute(variables: TVariables): Promise<TData>
Execute the mutation with the given variables.

pause

pause(): Promise<void>
Pause the mutation execution.

continue

continue(): Promise<TData>
Continue a paused mutation.

cancel

cancel(): Promise<void>
Cancel the mutation.

setState

setState(state: MutationState<TData, TError, TVariables, TContext>): void
Update the mutation state.

Examples

Accessing Mutation State

import { Mutation, QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const mutationCache = queryClient.getMutationCache()

// Get all mutations
const mutations = mutationCache.getAll()

mutations.forEach((mutation) => {
  console.log('Mutation ID:', mutation.mutationId)
  console.log('Status:', mutation.state.status)
  console.log('Data:', mutation.state.data)
  console.log('Error:', mutation.state.error)
  console.log('Variables:', mutation.state.variables)
})

Filtering Mutations

import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const mutationCache = queryClient.getMutationCache()

// Find pending mutations
const pendingMutations = mutationCache.findAll({
  status: 'pending',
})

console.log(`${pendingMutations.length} mutations in progress`)

Accessing Mutation Options

const mutation = mutationCache.find({ mutationKey: ['posts', 'create'] })

if (mutation) {
  console.log('Mutation Key:', mutation.options.mutationKey)
  console.log('Mutation Fn:', mutation.options.mutationFn)
  console.log('Retry:', mutation.options.retry)
}

Checking Mutation Status

const mutations = mutationCache.getAll()

const stats = mutations.reduce(
  (acc, mutation) => {
    acc[mutation.state.status]++
    return acc
  },
  { idle: 0, pending: 0, success: 0, error: 0 }
)

console.log('Mutation Statistics:', stats)

Subscribing to Mutations

import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const mutationCache = queryClient.getMutationCache()

// Subscribe to mutation cache changes
const unsubscribe = mutationCache.subscribe((event) => {
  if (event.type === 'added') {
    console.log('New mutation added:', event.mutation.mutationId)
  } else if (event.type === 'updated') {
    console.log('Mutation updated:', event.mutation.state.status)
  } else if (event.type === 'removed') {
    console.log('Mutation removed:', event.mutation.mutationId)
  }
})

// Clean up
unsubscribe()

Manually Creating Mutations

import { Mutation, QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()
const mutationCache = queryClient.getMutationCache()

const mutation = new Mutation({
  client: queryClient,
  mutationId: Date.now(),
  mutationCache,
  options: {
    mutationFn: async (variables) => {
      const response = await fetch('/api/posts', {
        method: 'POST',
        body: JSON.stringify(variables),
      })
      return response.json()
    },
  },
})

// Execute the mutation
mutation.execute({ title: 'Hello', body: 'World' })

Pausing and Resuming

import { Mutation } from '@tanstack/query-core'

// Create mutation
const mutation = new Mutation(config)

// Start execution
const promise = mutation.execute(variables)

// Pause if needed
if (shouldPause) {
  await mutation.pause()
  
  // Resume later
  await mutation.continue()
}

const result = await promise

Canceling Mutations

import { Mutation } from '@tanstack/query-core'

const mutation = new Mutation(config)

try {
  const promise = mutation.execute(variables)
  
  // Cancel after 5 seconds
  setTimeout(() => mutation.cancel(), 5000)
  
  const result = await promise
} catch (error) {
  if (error.name === 'CancelledError') {
    console.log('Mutation was cancelled')
  }
}

Mutation State

The mutation state object contains:
status
'idle' | 'pending' | 'success' | 'error'
The current status of the mutation
data
TData | undefined
The data returned by the mutation function (only set on success)
error
TError | null
The error thrown by the mutation function (only set on error)
variables
TVariables | undefined
The variables passed to the mutation function
context
TContext | undefined
The context returned by the onMutate callback
failureCount
number
The number of times the mutation has failed
failureReason
TError | null
The reason for the last failure
isPaused
boolean
Whether the mutation is currently paused
submittedAt
number
Timestamp when the mutation was submitted

Notes

  • Mutation is a low-level class typically created and managed by MutationCache
  • Each call to mutate() creates a new Mutation instance
  • Mutations are kept in the cache even after completion for state tracking
  • The mutationId is unique and auto-incremented
  • Mutations support pause/resume for handling network state changes
  • Failed mutations can be retried based on the retry configuration
  • State changes trigger notifications to observers and cache subscribers
  • Mutations are automatically removed from cache based on gcTime setting

Build docs developers (and LLMs) love