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

useMutation

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

定义于:packages/solid-query/src/useMutation.ts:170

与查询不同,修改通常用于创建/更新/删除数据或执行服务端副作用(server side-effects)。
useMutation 是用于此目的的原始 API。

类型参数

TData

TData = unknown

TError

TError = Error

TVariables

TVariables = void

TOnMutateResult

TOnMutateResult = unknown

参数

options

UseMutationOptions<TData, TError, TVariables, TOnMutateResult>

一个返回 UseMutationOptions 的 accessor。

options 属性

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

queryClient?

Accessor<QueryClient>

一个自定义 QueryClient 的 accessor。若未提供,则使用离当前组件最近的上下文中的 QueryClient。

返回值

UseMutationResult<TData, TError, TVariables, TOnMutateResult>

mutate/mutateAsync 还支持将 onSuccess/onError/onSettled 回调函数作为第二个参数传入,这在触发调用点副作用(例如导航)时非常有用,且无需将这些副作用耦合到共享的修改定义中。Hook 级回调(传入 options 的那些)会在每次修改时触发;而每次调用的回调仅对最近一次调用生效,且仅在组件仍处于挂载状态时触发 —— 若组件在修改完成前卸载,则会移除订阅,从而阻止这些回调执行。

返回结果属性

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

示例

TypeScript
1import { useMutation, useQueryClient } from '@tanstack/solid-query'2 3function TodoItem(props: { id: number }) {4  const queryClient = useQueryClient()5 6  const deleteTodoMutation = useMutation(() => ({7    mutationFn: deleteTodo,8    onSuccess: () => {9      queryClient.invalidateQueries({ queryKey: ['todos'] })10    },11  }))12 13  return (14    <button onClick={() => deleteTodoMutation.mutate({ id: props.id })} disabled={deleteTodoMutation.isPending}>15      Delete16    </button>17  )18}

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

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

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

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

译自上游 59d11de