SuperAPI AI Directory

tanstack-query-intent-compositions-automatic-invalidati-a8e9b778

Design & creation

View repository

Updated 10-16 06:24

About this skill

Core Patterns

Use local mutation callbacks for one-off behavior. Use MutationCache callbacks when the app wants a consistent invalidation policy for every mutation.

Global invalidation after successful mutations

import { MutationCache, QueryClient } from '@tanstack/react-query'

export const queryClient = new QueryClient({
  mutationCache: new MutationCache({
    onSuccess: (_data, _variables, _context, mutation) => {
      return queryClient.invalidateQueries({
        queryKey: mutation.options.mutationKey,
      })
    },
  }),
})

If a mutation has mutationKey: ['issues'], this invalidates matching issue queries. If it has no mutation key, this becomes a broad invalidation policy, so only use that deliberately.

Use meta for explicit invalidation tags

import { matchQuery, MutationCache, QueryClient } from '@tanstack/react-query'

const queryClient = new QueryClient({
  mutationCache: new MutationCache({
    onSuccess: (_data, _variables, _context, mutation) => {
      return queryClient.invalidateQueries({
        predicate: (query) =>
          mutation.meta?.invalidates?.some((queryKey) =>
            matchQuery({ queryKey }, query),
          ) ?? true,
      })
    },
  }),
})

Common Mistakes

HIGH Invalidating the whole app for every mutation

Wrong:

new MutationCache({
  onSuccess: () => queryClient.invalidateQueries(),
})

Correct:

new MutationCache({
  onSuccess: (_data, _variables, _context, mutation) =>
    queryClient.invalidateQueries({ queryKey: mutation.options.mutationKey }),
})

Global policies need scope. Reach for mutation keys or meta tags before invalidating everything.

Source: https://tkdodo.eu/blog/automatic-query-invalidation-after-mutations

HIGH Not returning invalidation when pending UI depends on refetch

Wrong:

onSuccess: () => {
  queryClient.invalidateQueries({ queryKey: ['todos'] })
}

Correct:

onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] })

Returning the promise keeps the mutation pending until the invalidation refetch completes.

Source: TanStack/query:docs/framework/react/guides/invalidations-from-mutations.md

MEDIUM Refetching data that should be static

Wrong:

useQuery({
  queryKey: ['build-info'],
  queryFn: fetchBuildInfo,
  staleTime: Infinity,
})

Correct:

useQuery({
  queryKey: ['build-info'],
  queryFn: fetchBuildInfo,
  staleTime: 'static',
})

If a query must not refetch even after broad manual invalidation, mark it with staleTime: 'static'.

Source: https://tkdodo.eu/blog/automatic-query-invalidation-after-mutations