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

useMutation

更新于 2026-11-02 Preact 查看英文原文 ↗
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/preact-query/src/useMutation.ts:188

与查询不同,修改通常用于创建/更新/删除数据或执行服务端副作用。 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 的位置读取的信息,例如 onError 和 onSuccess 回调函数(属于 MutationCache)。
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,则会在修改最终确定(settle)前等待其完成。
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 整数和实际 Error,返回下次重试前应延迟的毫秒数。默认为一个实现指数退避(上限为 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/preact-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/preact-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/preact-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,因此你可在它们全部成功后等待所有 Promise:

TypeScript
1import { useMutation, useQueryClient } from '@tanstack/preact-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/preact-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 文档(Preact 版)的非官方中文翻译,原文由上游团队维护,遵循 MIT 许可。 译文如有偏差,以英文原文为准。

译自上游 59d11de