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

useMutation

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

定义于:packages/vue-query/src/useMutation.ts:237

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

options 可以是普通对象、ref 或响应式 getter(() => ({ ... }))——若选项本身依赖其他响应式状态,请传入 getter。

类型参数

TData

TData = unknown

TError

TError = Error

TVariables

TVariables = void

TOnMutateResult

TOnMutateResult = unknown

参数

options

UseMutationOptions<TData, TError, TVariables, TOnMutateResult>

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

queryClient?

QueryClient

使用此参数可指定自定义的 QueryClient;否则将使用 VueQueryPlugin 提供的默认实例。

返回值

UseMutationReturnType<TData, TError, TVariables, TOnMutateResult>

mutate/mutateAsync 还支持以第二个参数形式传入每次调用专属的 onSuccess/onError/onSettled 回调函数,适用于在调用点触发副作用(例如导航),而无需将其耦合到共享的 修改 定义中。Hook 级回调(传给 options 的)会在每次 修改 时触发;而每次调用专属的回调仅对最近一次调用生效。

参见

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

示例

HTML
1<script setup lang="ts">2import { useMutation, useQueryClient } from '@tanstack/vue-query'34const queryClient = useQueryClient()56const addMutation = useMutation({7  mutationFn: addTodo,8  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),9})1011function onAdd() {12  addMutation.mutate('Item', {13    onError: (error) => console.error('Failed to add item:', error),14  })15}16</script>17 18<template>19  <button @click="onAdd">Add</button>20</template>

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

HTML
1<script setup lang="ts">2import { useMutation, useQueryClient } from '@tanstack/vue-query'34const queryClient = useQueryClient()56const addMutation = useMutation({7  mutationFn: addTodo,8  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),9})10</script>11 12<template>13  <div v-if="addMutation.isPending.value">Adding todo...</div>14  <div v-else>15    <div v-if="addMutation.isError.value">An error occurred: {{ addMutation.error.value.message }}</div>16    <button @click="addMutation.mutate('Item')">Add</button>17  </div>18</template>

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

HTML
1<script setup lang="ts">2import { useMutation, useQueryClient } from '@tanstack/vue-query'34const queryClient = useQueryClient()56const addMutation = useMutation({7  mutationFn: addTodo,8  onMutate: async (newTodo: string) => {9    await queryClient.cancelQueries({ queryKey: ['todos'] })10    const previousTodos = queryClient.getQueryData<Array<string>>(['todos'])1112    queryClient.setQueryData<Array<string>>(['todos'], (old) => [13      ...(old ?? []),14      newTodo,15    ])1617    // 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</script>28 29<template>30  <button @click="addMutation.mutate('Item')">Add</button>31</template>

传给 mutate 的每次调用专属回调仅对最后一次调用生效 —— mutateAsync 则为每次调用返回一个 Promise,因此你可在它们全部成功后等待所有结果:

HTML
1<script setup lang="ts">2import { useMutation, useQueryClient } from '@tanstack/vue-query'34const queryClient = useQueryClient()56const addMutation = useMutation({7  mutationFn: addTodo,8  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),9})1011async 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</script>19 20<template>21  <button @click="handleAddAll(['Todo 1', 'Todo 2', 'Todo 3'])">Add all</button>22</template>

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

HTML
1<script setup lang="ts">2import { useMutation, useQueryClient } from '@tanstack/vue-query'34const queryClient = useQueryClient()56const addMutation = useMutation({7  mutationFn: addTodo,8  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),9})1011async function handleAddAll(todos: Array<string>) {12  const addResults = await Promise.allSettled(13    todos.map((todo) => addMutation.mutateAsync(todo)),14  )1516  addResults.forEach((addResult, index) => {17    if (addResult.status === 'rejected') {18      console.error(`Failed to add "${todos[index]}":`, addResult.reason)19    }20  })21}22</script>23 24<template>25  <button @click="handleAddAll(['Todo 1', 'Todo 2', 'Todo 3'])">Add all</button>26</template>

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

译自上游 59d11de