Files
upstream-tanstack-query/docs/framework/lit/guides/query-invalidation.md
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

id, title
id title
query-invalidation Query Invalidation

Waiting for queries to become stale is not always enough. After a mutation succeeds, you often know that related cached data is out of date. Use queryClient.invalidateQueries to mark matching queries stale and refetch active observers.

queryClient.invalidateQueries()

queryClient.invalidateQueries({
  queryKey: ['todos'],
})

When a query is invalidated:

  • It is marked stale, overriding any staleTime
  • If a matching query is active in a controller, it can refetch in the background

Invalidation from Mutations

private readonly addTodo = createMutationController(this, {
  mutationFn: addTodo,
  onSuccess: async () => {
    await queryClient.invalidateQueries({ queryKey: ['todos'] })
  },
})

Use this pattern when the mutation result tells you related cached data is stale. The Pagination example shows invalidation after project mutations.

Query Matching

Match a group of queries by prefix:

queryClient.invalidateQueries({ queryKey: ['projects'] })

Both of these query keys match:

const projectsListKey = ['projects']
const projectsPageKey = ['projects', 1, 250, false]

Use a more specific key when only one slice should be invalidated:

queryClient.invalidateQueries({
  queryKey: ['projects', this.page],
})

Use exact: true to match only the exact key:

queryClient.invalidateQueries({
  queryKey: ['projects'],
  exact: true,
})

Manual Cache Updates

Invalidation is usually simpler than normalized cache updates. When you do need immediate UI updates, combine targeted cache writes with invalidation:

queryClient.setQueryData<TodosResponse>(['todos'], (existing) => {
  if (!existing) return existing

  return {
    ...existing,
    items: [...existing.items, createdTodo],
  }
})

await queryClient.invalidateQueries({ queryKey: ['todos'] })

For rollback with optimistic updates, see the mutation guide and the Pagination example.