last update
Jun 2, 2026
license
MITv1.0.0
format
SKILL.md
- Install
// Downloads SKILL.md into ~/.claude/skills/tanstack-query-pro/
$ curl -fsSL --create-dirs -o ~/.claude/skills/tanstack-query-pro/SKILL.md https://claudeskil.com/skills/tanstack-query-pro/SKILL.md - Invoke
// Inside Claude Code, type the skill name as a slash command
> /tanstack-query-pro give my landing page a hero treatment - Or copy this from the README
// extracted tsx block
$ const useUpdateTodo = () => { const qc = useQueryClient() return useMutation({ mutationFn: patchTodo, onMutate: async (next) => { await qc.cancelQueries({ queryKey: ['todos'] })
- name:
- TanStack Query Pro
- slug:
- tanstack-query-pro
- version:
- v1.0.0
- license:
- MIT
- author:
- @chiragthummar16
- categories:
- tags:
- #react-query#tanstack#state#data-fetching#react
- description:
TanStack Query (React Query) — queries, mutations, optimistic updates, infinite scroll, prefetch.
README.md
TanStack Query Pro
A practitioner's playbook for building data layers with TanStack Query (formerly React Query) v5. This skill encodes the conventions that keep a query cache predictable at scale: stable keys, deliberate cache lifetimes, surgical invalidation, and mutations that update the UI before the server replies. It's aimed at React developers past the "it works on my machine" stage who are wrestling with stale data, race conditions, or duplicate requests in production.
When to use it
- You have
queryKeyarrays scattered as string literals and invalidation has become guesswork. - A list shows stale items after an edit, or a mutation flickers between optimistic and real state.
- You're building infinite scroll, search-as-you-type, or paginated tables and need
keepPreviousDatabehavior. - You're moving to the App Router / RSC and want server-prefetched data hydrated into the client cache without a flash.
How it works
The skill works against the real v5 API surface. It standardizes queryKey factories (e.g. todos.list(filters) returning ['todos', 'list', filters]) so keys stay serializable and collision-free. It clarifies the two timers people conflate: staleTime (how long data is considered fresh before a background refetch) versus gcTime (how long unused cache entries survive before garbage collection). For writes, it sets up useMutation with the onMutate → onError → onSettled lifecycle: snapshot via getQueryData, write via setQueryData, roll back on failure, then invalidateQueries to reconcile. It covers useInfiniteQuery with getNextPageParam, useSuspenseQuery for Suspense/RSC boundaries, and server prefetch via prefetchQuery + dehydrate/HydrationBoundary.
Example
curl -fsSL --create-dirs -o ~/.claude/skills/tanstack-query-pro/SKILL.md https://claudeskil.com/skills/tanstack-query-pro/SKILL.md
const useUpdateTodo = () => {
const qc = useQueryClient()
return useMutation({
mutationFn: patchTodo,
onMutate: async (next) => {
await qc.cancelQueries({ queryKey: ['todos'] })
const prev = qc.getQueryData(['todos'])
qc.setQueryData(['todos'], (old) => old.map(t => t.id === next.id ? next : t))
return { prev }
},
onError: (_e, _next, ctx) => qc.setQueryData(['todos'], ctx.prev),
onSettled: () => qc.invalidateQueries({ queryKey: ['todos'] }),
})
}
Tips & gotchas
cancelQueriesinsideonMutateis not optional — skip it and an in-flight refetch can clobber your optimistic write.staleTimedefaults to0, so every mount refetches. Raise it for data that doesn't change per-view.invalidateQueries({ queryKey: ['todos'] })matches by prefix, invalidating every key that starts withtodos. Use this rather than removing entries.- With
useSuspenseQuery,datais neverundefinedand there is noisLoading— handle the pending state with a<Suspense>boundary instead.
FAQ
staleTime vs gcTime? staleTime governs freshness (when to refetch); gcTime (was cacheTime) governs how long an inactive query stays in memory. They're independent.
How do I keep the old page visible during pagination? Use the placeholderData: keepPreviousData helper in v5 so the previous result renders while the next page loads.
Does prefetched server data avoid a client refetch? Yes, if you set staleTime so the hydrated data is still fresh on mount; otherwise it refetches immediately.
$ cat reviews/