Capítulo 27 de 80

Chapter 27: Query Invalidation

Core Idea

queryClient.invalidateQueries({ queryKey }) marks matching queries stale (overriding any configured staleTime) and, if currently rendered, triggers an immediate background refetch — matching is by key prefix by default, so ['todos'] invalidates ['todos'], ['todos', {page: 1}], and every other query starting with 'todos'.

Key Concepts

  • Two effects of invalidation: the query is marked stale (bypassing staleTime), and if it has active observers (currently rendered via useQuery), it's refetched in the background immediately rather than waiting for the next natural trigger.
  • Prefix matching by default: invalidateQueries({ queryKey: ['todos'] }) matches every query whose key starts with ['todos'], not just an exact match — ['todos', { page: 1 }] is included.
  • Narrowing the match: pass a more specific key (['todos', { type: 'done' }]) to only match that shape and its extensions; pass exact: true to match only the given key with no extra segments at all.
  • Predicate matching: for logic beyond prefix/exact matching, invalidateQueries({ predicate: (query) => ... }) receives every cached Query instance and lets you return true/false per query — e.g. invalidate only todos queries with version >= 10.
  • Invalidate everything: queryClient.invalidateQueries() with no arguments invalidates every query in the cache.
  • Design philosophy: rather than normalized-cache-style automatic local patching, TanStack Query deliberately favors targeted invalidation + background refetch (and, separately, direct atomic updates via setQueryData) as the two supported update strategies.

Code Examples

// Prefix match — invalidates ['todos'] and ['todos', {page:1}] alike
queryClient.invalidateQueries({ queryKey: ['todos'] })

// Exact match only — does NOT invalidate ['todos', {type:'done'}]
queryClient.invalidateQueries({ queryKey: ['todos'], exact: true })

// Predicate — arbitrary custom matching logic
queryClient.invalidateQueries({
  predicate: (query) => query.queryKey[0] === 'todos' && query.queryKey[1]?.version >= 10,
})
  • What it demonstrates: the three matching granularities — prefix (default), exact, and predicate — for the same invalidateQueries call.

Key Takeaways

  1. Default (prefix) matching is usually what you want when a mutation affects "all todos regardless of filters" — reach for exact: true only when you specifically must not touch derived/filtered variants.
  2. predicate is the escape hatch for matching logic that key-prefix alone can't express (e.g. numeric comparisons on key segments).
  3. Invalidation is the declarative default; only reach for manual setQueryData writes (Chapter 29) when refetching is provably too slow or unnecessary for a specific case.

Connects To

  • Invalidations from Mutations: where this is typically called from (onSuccess).
  • Filters: the shared filter object (queryKey, exact, predicate, etc.) reused across invalidateQueries, removeQueries, and other bulk cache operations.