--- id: useMutation title: useMutation --- ```ts function useMutation(options, queryClient?): UseMutationResult; ``` Defined in: [packages/preact-query/src/useMutation.ts:192](https://github.com/TanStack/query/blob/main/packages/preact-query/src/useMutation.ts#L192) Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. `useMutation` is the hook for that. ## Type Parameters ### TData `TData` = `unknown` ### TError `TError` = `Error` ### TVariables `TVariables` = `void` ### TOnMutateResult `TOnMutateResult` = `unknown` ## Parameters ### options [`UseMutationOptions`](../interfaces/UseMutationOptions.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\> The [UseMutationOptions](../interfaces/UseMutationOptions.md) to use — everything you can pass to `useMutation`. ### queryClient? [`QueryClient`](../classes/QueryClient.md) Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will be used. ## Returns [`UseMutationResult`](../type-aliases/UseMutationResult.md)\<`TData`, `TError`, `TVariables`, `TOnMutateResult`\> `mutate`/`mutateAsync` also accept per-call `onSuccess`/`onError`/`onSettled` callbacks as a second argument, useful for triggering call-site side effects (e.g. navigation) without coupling them to the shared mutation definition. Hook-level callbacks (passed to `options`) fire for every mutation; per-call callbacks fire only for the latest call you've made, and only while the component is still mounted — unmounting before the mutation settles removes the subscription and prevents them from firing. ## See [mutationOptions](mutationOptions.md) to share these options across multiple `useMutation` call sites, or to look the mutation up elsewhere via its `mutationKey` (e.g. with `useMutationState`). ## Examples ```tsx import { useMutation, useQueryClient } from '@tanstack/preact-query' function AddTodo() { const queryClient = useQueryClient() const addMutation = useMutation({ mutationFn: addTodo, onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), }) return ( ) } ``` Rendering the mutation's own state, rather than just firing it off: ```tsx import { useMutation, useQueryClient } from '@tanstack/preact-query' function AddTodo() { const queryClient = useQueryClient() const addMutation = useMutation({ mutationFn: addTodo, onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), }) return (
{addMutation.isPending ? ( 'Adding todo...' ) : ( <> {addMutation.isError ? (
An error occurred: {addMutation.error.message}
) : null} )}
) } ``` Optimistic update via `onMutate`, rolling back on `onError`: ```tsx import { useMutation, useQueryClient } from '@tanstack/preact-query' function AddTodo() { const queryClient = useQueryClient() const addMutation = useMutation({ mutationFn: addTodo, onMutate: async (newTodo) => { await queryClient.cancelQueries({ queryKey: ['todos'] }) const previousTodos = queryClient.getQueryData>(['todos']) queryClient.setQueryData>(['todos'], (old) => [ ...(old ?? []), newTodo, ]) // Passed to `onError` as `onMutateResult` if the mutation fails. return { previousTodos } }, onError: (_err, _newTodo, onMutateResult) => { queryClient.setQueryData(['todos'], onMutateResult?.previousTodos) }, onSettled: () => { queryClient.invalidateQueries({ queryKey: ['todos'] }) }, }) return ( ) } ``` Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a promise per call instead, so you can wait for all of them when they succeed: ```tsx import { useMutation, useQueryClient } from '@tanstack/preact-query' function AddTodos() { const queryClient = useQueryClient() const addMutation = useMutation({ mutationFn: addTodo, onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), }) async function handleAddAll(todos: Array) { try { await Promise.all(todos.map((todo) => addMutation.mutateAsync(todo))) } catch (error) { console.error('Failed to add todos:', error) } } return ( ) } ``` If some of the mutations above can fail independently of the others, and you want to know which ones did — rather than losing that information the moment the first one rejects — swap `Promise.all` for `Promise.allSettled`: ```tsx import { useMutation, useQueryClient } from '@tanstack/preact-query' function AddTodos() { const queryClient = useQueryClient() const addMutation = useMutation({ mutationFn: addTodo, onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), }) async function handleAddAll(todos: Array) { const addResults = await Promise.allSettled( todos.map((todo) => addMutation.mutateAsync(todo)), ) addResults.forEach((addResult, index) => { if (addResult.status === 'rejected') { console.error(`Failed to add "${todos[index]}":`, addResult.reason) } }) } return ( ) } ```