---
id: query.mutation-cache-update
kind: recipe
product: query
framework: react
locale: en
revision: 2
sourceCheckedOn: "2026-08-03"
versionRange: "^5"
verifiedAgainst: "@tanstack/react-query@5.101.4"
contentModel: 2
packages:
  - "@tanstack/react-query"
tasks:
  - "create-mutation"
  - "update-query-cache"
  - "invalidate-query"
sourceRefs:
  - "https://tanstack.com/query/latest/docs/framework/react/guides/mutations"
  - "https://tanstack.com/query/latest/docs/framework/react/guides/updates-from-mutation-responses"
  - "https://tanstack.com/query/latest/docs/framework/react/guides/invalidations-from-mutations"
---

# Update cache from a mutation response

> Use setQueryData when the write response contains the complete entity; invalidate when the correct cache cannot be derived.

## Execution contract

- **Use when:** Use when a mutation returns the authoritative current entity and can update an exact cache entry.
- **Avoid when:** Prefer bounded invalidation when the response is partial or affects an unknown set of lists.
- **Preconditions:** List affected query keys, the server response type, and the old value that must survive failure.
- **Verification:** After success, detail and list agree; after failure, old cache remains and unrelated queries are not invalidated.
- **Failure mode:** Divergent list and detail data indicates one cache was skipped or keys differ; centralize key factories and update scope.
- **Security:** A client cache write is not proof of persistence or authorization; use server-confirmed responses only.

## Write through directly

mutationFn returns the server-created object. onSuccess creates a new array with functional setQueryData. Never mutate current in place.

File: `src/features/issues/useCreateIssue.ts`

```tsx
export function useCreateIssue() {
  const queryClient = useQueryClient()

  return useMutation({
    mutationFn: createIssue,
    onSuccess: (created) => {
      queryClient.setQueryData<Issue[]>(['issues'], (current = []) => [
        created,
        ...current,
      ])
    },
  })
}
```

## When to invalidate

If the server reorders lists, computes aggregates, applies permission filters, or omits relevant fields, await invalidateQueries({ queryKey: ['issues'] }) after success. Do not blindly set and invalidate together.

## Errors and concurrency

Use isPending to prevent duplicate submission or show progress and isError for recoverable feedback. Add optimistic updates only after implementing cancellation, snapshot, and rollback.

## Official sources

- https://tanstack.com/query/latest/docs/framework/react/guides/mutations
- https://tanstack.com/query/latest/docs/framework/react/guides/updates-from-mutation-responses
- https://tanstack.com/query/latest/docs/framework/react/guides/invalidations-from-mutations
