译零 TransZero · TanStack Query 中文文档
主站

useMutation

更新于 2026-11-02 React 查看英文原文 ↗
TypeScript
1function useMutation<TData = unknown, TError = Error, TVariables = void, TOnMutateResult = unknown>(options: UseMutationOptions<TData, TError, TVariables, TOnMutateResult>, queryClient?: QueryClient): UseMutationResult<TData, TError, TVariables, TOnMutateResult>;

定义于:packages/react-query/src/useMutation.ts:187

与查询不同,修改通常用于创建/更新/删除数据或执行服务端副作用。 useMutation 是用于此目的的 Hook。

类型参数

TData

TData = unknown

TError

TError = Error

TVariables

TVariables = void

TOnMutateResult

TOnMutateResult = unknown

参数

options

UseMutationOptions<TData, TError, TVariables, TOnMutateResult>

要使用的 UseMutationOptions —— 即所有可传给 useMutation 的选项。

options 属性

属性 类型 默认值 描述
gcTime? number undefined 未使用/非活跃修改在被垃圾回收前保留在内存中的毫秒数。默认为 5 * 60 * 1000(5 分钟),SSR 期间为 Infinity。
meta? Record<string, unknown> undefined 要存储在修改缓存条目上的额外负载。可用于传递可在任何存在 mutation 的位置读取的信息,例如 MutationCache 的 onError 和 onSuccess 回调。
mutationFn? (variables: TVariables, context: MutationFunctionContext) => Promise<TData> undefined 执行该修改所运行的异步任务的函数。必需,除非已通过 queryClient.setMutationDefaults 为匹配的 mutationKey 设置了默认修改函数。接收传给 mutate 的 variables,以及一个包含 QueryClient、mutationKey 和 meta 的 MutationFunctionContext。必须返回一个解析修改数据的 Promise。
mutationKey? readonly unknown[] undefined 此修改所用的键。可选,但若要继承通过 queryClient.setMutationDefaults 注册的默认值,或要将此修改与 useMutationState 或 queryClient.isMutating 匹配,则为必需。
networkMode? "online" | "always" | "offlineFirst" 'online' 控制是否允许修改基于当前网络连接状态运行。参见 网络模式 获取更多信息。
onError? (error: TError, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: MutationFunctionContext) => unknown undefined 当修改遇到错误时触发该函数,并传入错误。若返回 Promise,则会在 onSettled 运行前等待其完成。
onMutate? (variables: TVariables, context: MutationFunctionContext) => TOnMutateResult | Promise<TOnMutateResult> undefined 在修改函数运行前触发该函数,并接收相同的变量。适用于乐观更新,即在期望修改成功的情况下提前应用更新。其返回值作为 onMutateResult 传给 onSuccess、onError 和 onSettled,乐观更新通常在此处回滚。若返回 Promise,则会在修改函数运行前等待其完成。
onSettled? (data: TData | undefined, error: TError | null, variables: TVariables, onMutateResult: TOnMutateResult | undefined, context: MutationFunctionContext) => unknown undefined 当修改成功或出错时触发该函数,并传入数据或错误。若返回 Promise,则会在修改最终确定前等待其完成。
onSuccess? (data: TData, variables: TVariables, onMutateResult: TOnMutateResult, context: MutationFunctionContext) => unknown undefined 当修改成功时触发该函数,并传入修改结果。若返回 Promise,则会在 onSettled 运行前等待其完成。
retry? | number | false | true | ((failureCount: number, error: TError) => boolean) 0 若为 false,失败的修改默认不重试;若为 true,失败的修改将无限重试;若设为整数(如 3),则失败的修改将重试直至失败次数达到该数值;若设为函数 (failureCount, error) => boolean,则失败的修改将重试直至该函数返回 false。
retryDelay? number | ((failureCount: number, error: TError) => number) undefined 该函数接收一个 retryAttempt 整数和实际错误,并返回下次尝试前应延迟的毫秒数。默认为一个应用指数退避(上限为 30 秒)的函数。
scope? MutationScope undefined 控制此修改是与其他修改并行运行还是等待轮到自己。共享相同 scope.id 的修改将按启动顺序串行运行。若未指定作用域,则修改将在触发后立即运行。
throwOnError? boolean | ((error: TError) => boolean) false 是否应抛出错误而非设置 error 属性。若设为 true,所有错误都将抛出至最近的错误边界。若设为函数,则会传入错误并应返回布尔值,指示是否抛出错误(true)或将其作为状态返回(false)。

queryClient?

QueryClient

使用此参数可指定自定义 QueryClient。否则,将使用最近上下文中的 QueryClient。

返回值

UseMutationResult<TData, TError, TVariables, TOnMutateResult>

mutate/mutateAsync 还接受以第二个参数形式传入的每次调用专属 onSuccess/onError/onSettled 回调,这有助于在不将副作用(例如导航)耦合到共享修改定义的情况下触发调用点副作用。Hook 级回调(传给 options)对每次修改均触发;每次调用专属回调仅对最近一次调用触发,且仅当组件仍处于挂载状态时才触发 —— 若在修改最终确定前卸载组件,则会移除订阅并阻止这些回调触发。

返回值属性

基于 MutationObserverBaseResult 构建。参见上方类型定义了解其变更内容。

抛出

当 throwOnError 为 true 或对其返回 true 时,抛出修改错误,以便其被抛出至最近的错误边界。

参见

mutationOptions 可用于在多个 useMutation 调用点间共享这些选项,或通过其 mutationKey(例如使用 useMutationState)在其他位置查找该修改。

示例

TypeScript
1import { useMutation, useQueryClient } from '@tanstack/react-query'2 3function AddTodo() {4  const queryClient = useQueryClient()5 6  const addMutation = useMutation({7    mutationFn: addTodo,8    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),9  })10 11  return (12    <button13      onClick={() =>14        addMutation.mutate('Item', {15          onError: (error) => console.error('Failed to add item:', error),16        })17      }18    >19      Add20    </button>21  )22}

渲染修改自身的状态,而不仅仅是触发它:

TypeScript
1import { useMutation, useQueryClient } from '@tanstack/react-query'2 3function AddTodo() {4  const queryClient = useQueryClient()5 6  const addMutation = useMutation({7    mutationFn: addTodo,8    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),9  })10 11  return (12    <div>13      {addMutation.isPending ? (14        'Adding todo...'15      ) : (16        <>17          {addMutation.isError ? (18            <div>An error occurred: {addMutation.error.message}</div>19          ) : null}20          <button onClick={() => addMutation.mutate('Item')}>Add</button>21        </>22      )}23    </div>24  )25}

通过 onMutate 实现乐观更新,并在 onError 中回滚:

TypeScript
1import { useMutation, useQueryClient } from '@tanstack/react-query'2 3function AddTodo() {4  const queryClient = useQueryClient()5 6  const addMutation = useMutation({7    mutationFn: addTodo,8    onMutate: async (newTodo) => {9      await queryClient.cancelQueries({ queryKey: ['todos'] })10      const previousTodos = queryClient.getQueryData<Array<string>>(['todos'])11 12      queryClient.setQueryData<Array<string>>(['todos'], (old) => [13        ...(old ?? []),14        newTodo,15      ])16 17      // Passed to `onError` as `onMutateResult` if the mutation fails.18      return { previousTodos }19    },20    onError: (_err, _newTodo, onMutateResult) => {21      queryClient.setQueryData(['todos'], onMutateResult?.previousTodos)22    },23    onSettled: () => {24      queryClient.invalidateQueries({ queryKey: ['todos'] })25    },26  })27 28  return (29    <button onClick={() => addMutation.mutate('Item')}>Add</button>30  )31}

传给 mutate 的每次调用专属回调仅对最后一次调用触发 — mutateAsync 则为每次调用提供一个 Promise,因此你可在它们全部成功后等待全部完成:

TypeScript
1import { useMutation, useQueryClient } from '@tanstack/react-query'2 3function AddTodos() {4  const queryClient = useQueryClient()5 6  const addMutation = useMutation({7    mutationFn: addTodo,8    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),9  })10 11  async function handleAddAll(todos: Array<string>) {12    try {13      await Promise.all(todos.map((todo) => addMutation.mutateAsync(todo)))14    } catch (error) {15      console.error('Failed to add todos:', error)16    }17  }18 19  return (20    <button onClick={() => handleAddAll(['Todo 1', 'Todo 2', 'Todo 3'])}>21      Add all22    </button>23  )24}

若上述某些修改可独立于其他修改失败,且你想知道具体哪些失败(而非在第一个拒绝时就丢失该信息),请将 Promise.all 替换为 Promise.allSettled:

TypeScript
1import { useMutation, useQueryClient } from '@tanstack/react-query'2 3function AddTodos() {4  const queryClient = useQueryClient()5 6  const addMutation = useMutation({7    mutationFn: addTodo,8    onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),9  })10 11  async function handleAddAll(todos: Array<string>) {12    const addResults = await Promise.allSettled(13      todos.map((todo) => addMutation.mutateAsync(todo)),14    )15 16    addResults.forEach((addResult, index) => {17      if (addResult.status === 'rejected') {18        console.error(`Failed to add "${todos[index]}":`, addResult.reason)19      }20    })21  }22 23  return (24    <button onClick={() => handleAddAll(['Todo 1', 'Todo 2', 'Todo 3'])}>25      Add all26    </button>27  )28}

本页为 TanStack Query 文档(React 版)的非官方中文翻译,原文由上游团队维护,遵循 MIT 许可。 译文如有偏差,以英文原文为准。

译自上游 59d11de