Files
upstream-mirror 3a013ccdfe
Some checks failed
autofix.ci / autofix (push) Failing after 4s
Release / Release (push) Has been skipped
GitHub Actions Security Analysis / Run zizmor (push) Failing after 2s
snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
2026-09-16 01:13:08 +05:00

2.0 KiB

TanStack Query — Next.js App Router Optimistic Updates

This example demonstrates optimistic updates with TanStack Query v5 in a Next.js 14 App Router project.

What it shows

A todo list where items appear in the UI immediately after submission — before the server confirms. The server randomly fails ~30% of the time so you can observe automatic rollback behaviour.

Two approaches are shown side by side via a tab toggle:

Approach 1 — Via UI Variables (simpler)

Render the pending item directly from mutation.variables. No cache touching required. On error, the pending item simply disappears and an error message is shown.

const mutation = useMutation({ mutationFn: addTodo, onSettled: invalidate })

// In JSX:
{mutation.isPending && <li style={{ opacity: 0.5 }}>{mutation.variables}</li>}

Best when: the mutation input maps 1-to-1 to what you'd show while pending.

Approach 2 — Via Cache Manipulation (onMutate + rollback)

onMutate cancels in-flight refetches, snapshots the current cache, and writes an optimistic item directly into the cache. onError restores the snapshot.

const mutation = useMutation({
  mutationFn: addTodo,
  onMutate: async (text) => {
    await queryClient.cancelQueries({ queryKey: ['todos'] })
    const previousTodos = queryClient.getQueryData<Todo[]>(['todos'])
    queryClient.setQueryData<Todo[]>(['todos'], (old = []) => [
      ...old,
      optimistic,
    ])
    return { previousTodos }
  },
  onError: (_err, _vars, context) => {
    queryClient.setQueryData(['todos'], context?.previousTodos)
  },
  onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
})

Best when: you need fine-grained control or the optimistic shape differs from mutation.variables.

Running the example

npm install
npm run dev

Open http://localhost:3000.

Learn more