useMutation useMutation Write Operations

Last updated: 2026-11-02

useMutation useMutation Write Operations

useMutation manages the async state of write operations (POST, PUT, DELETE): mutate triggers the request, isPending and isError report the progress, and onSuccess invalidates the related queries so the list refreshes on its own. It does not cache data, it only manages this one submission. That division of labour is what makes query and mutation a natural pair. You can also pass callbacks per call, so one hook instance can serve several different forms without sharing their state.

GroupData & Engineering
KindHook
SinceTanStack Query v5

ℹ️ Info The editor transpiles JSX to JavaScript and renders the real UI in a sandbox; components mount automatically — no manual render call needed.

📝 Syntax

import { useMutation, useQueryClient } from '@tanstack/react-query'

const qc = useQueryClient()
const mutation = useMutation({
  mutationFn: newTodo => fetch('/api/todos', {
    method: 'POST',
    body: JSON.stringify(newTodo)
  }).then(r => r.json()),
  onSuccess: () => {
    qc.invalidateQueries({ queryKey: ['todos'] })  // the list turns stale -> it refetches itself
  }
})

mutation.mutate({ title: 'New task' })   // fire the submission

⚙️ Parameters

mutationFnRequired. The async function that performs the write operation; the variables passed to mutate(variables) arrive as its argument.
onSuccess / onErrorCallback hooks: invalidate queries after a success, show a message after a failure; they can also be overridden per call with mutate(v, { onSuccess }).

Returns:Returns { mutate, isPending, isError, data, error }: mutate(variables) fires the request (it returns no Promise), while mutateAsync does return a Promise.

▶ Example

The example runs out of the box: it auto-renders when expanded, and edits take effect instantly.

Output:

The submit button turns into "Saving…" and stays disabled for one second, then the list gains an entry and a success message appears - the full flow of mutate, isPending and onSuccess (simulated demo).

💡 Key Points

⚠️ Warning mutate returns no Promise (the result arrives through the callbacks); when you need to await inside an async function use mutateAsync and handle the errors yourself.
💡 Tip After a successful write call invalidateQueries instead of patching the list by hand - let the cache layer refetch so the server and the client stay in sync.
ℹ️ Info Optimistic updates (onMutate changes the cache first, a failure rolls it back) also fit into the callback chain of useMutation, which makes the submit feel instant.
More case studies coming soon.

📚 Related Tutorials

❓ FAQ

Q What is the core difference between useMutation and useQuery?
A A query reads data, comes with a cache and can refetch in the background; a mutation writes data, is not cached and is triggered explicitly by a user action. Read with a query, write with a mutation.
Q How does the list update itself after a submit?
A Call queryClient.invalidateQueries({ queryKey: ['todos'] }) in onSuccess: the list query is marked as stale and useQuery refetches the latest data.
Q How do I prevent double submits?
A Disable the button while isPending is true (as in the example) or check the status before submitting; the server still needs idempotency as a safety net.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏