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

createMutation

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

定义于:packages/solid-query/src/index.ts:80

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

类型参数

TData

TData = unknown

TError

TError = Error

TVariables

TVariables = void

TOnMutateResult

TOnMutateResult = unknown

参数

options

UseMutationOptions<TData, TError, TVariables, TOnMutateResult>

一个返回待使用的 UseMutationOptions 的访问器。

queryClient?

Accessor<QueryClient>

一个自定义 QueryClient 的访问器。否则将使用最近上下文中的那个。

返回值

UseMutationResult<TData, TError, TVariables, TOnMutateResult>

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

示例

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,因此你可在所有调用成功后等待全部完成:

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