useMutation
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。
返回值
UseMutationResult<TData, TError, TVariables, TOnMutateResult>
mutate/mutateAsync 还接受以第二个参数形式传入的每次调用专属 onSuccess/onError/onSettled 回调函数,这有助于在不将副作用(例如导航)耦合到共享修改定义的情况下,在调用点触发副作用。Hook 级回调(传给 options)对每次修改均会触发;而每次调用专属回调仅对最近一次调用生效,且仅在组件仍挂载时触发 —— 若在修改最终确定前卸载组件,则会移除订阅,防止回调触发。
返回值属性
基于 MutationObserverBaseResult 构建。参见上方类型定义了解其具体变更。
抛出异常
当 throwOnError 为 true 或对其返回 true 时,抛出修改错误,以便其能被传递至最近的错误边界。
参见
mutationOptions 可用于在多个 useMutation 调用点间共享这些选项,或通过其 mutationKey(例如使用 useMutationState)在其他位置查找该修改。
示例
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}渲染修改自身的状态,而不仅只是触发它:
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 中回滚:
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:
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:
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}