← marketplace
engineerslibrarysha:14954140544ec8femanual
tanstack-query
Use when managing server state in a frontend app: fetching, caching, background refetching, and synchronizing async data without writing manual loading logic.
Install confidence
curl --create-dirs -fsSL https://skillmake.xyz/i/tanstack-query -o ~/.claude/skills/tanstack-query/SKILL.md
Pinned content
sha:14954140544ec8fe
Generated with
manual
Source
tanstack.com
The file served at /api/marketplace/tanstack-query-14954140/raw matches this hash. Inspect before install, then copy the command.
5,571 chars · ~1,393 tokens
--- name: tanstack-query description: "Use when managing server state in a frontend app: fetching, caching, background refetching, and synchronizing async data without writing manual loading logic." source: https://tanstack.com/query/latest/docs/framework/react/overview generated: 2026-07-02T18:43:37.726Z category: library audience: engineers --- ## When to use - Fetching and caching server data in React, Vue, Svelte, Solid, or Angular apps - Eliminating manual loading/error/refetch boilerplate around async data - Keeping UI in sync with the server via background refetch and cache invalidation - Implementing optimistic updates, pagination, or infinite scroll over a query cache ## Key concepts ### Query keys An array that uniquely identifies cached data, e.g. ['todos', id]. The key drives caching, refetching, and invalidation; changing any part triggers a new fetch. ### staleTime vs gcTime staleTime is how long data is considered fresh (no auto-refetch); gcTime (formerly cacheTime) is how long inactive/unused data stays in cache before garbage collection. Default staleTime is 0, gcTime is 5 minutes. ### QueryClient and provider A single QueryClient holds the cache. Wrap the app in QueryClientProvider so hooks can access it. Defaults can be set via defaultOptions. ### Mutations useMutation handles create/update/delete. Pair onSuccess/onSettled with queryClient.invalidateQueries to refetch affected data, or perform optimistic updates with onMutate. ### Invalidation queryClient.invalidateQueries({ queryKey }) marks matching queries stale and refetches active ones, the canonical way to reflect server changes after a mutation. ### Status flags Queries expose status (pending/error/success) plus fetchStatus (fetching/idle), isPending, isError, isFetching, and data. isFetching is true on background refetches even when data exists. ## API reference ``` new QueryClient(options) + <QueryClientProvider client={...}> ``` Create the cache and provide it to the component tree. ``` import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 60_000 } }, }); export function App() { return ( <QueryClientProvider client={queryClient}> <Todos /> </QueryClientProvider> ); } ``` ``` useQuery({ queryKey, queryFn, ...options }) ``` Read async data; returns data, error, isPending, isError, refetch, and more. ``` import { useQuery } from '@tanstack/react-query'; function Todos() { const { data, isPending, isError } = useQuery({ queryKey: ['todos'], queryFn: () => fetch('/api/todos').then((r) => r.json()), }); if (isPending) return <p>Loading</p>; if (isError) return <p>Error</p>; return <ul>{data.map((t) => <li key={t.id}>{t.title}</li>)}</ul>; } ``` ``` useMutation({ mutationFn, onSuccess, onMutate }) ``` Perform writes and react to their lifecycle; call mutate/mutateAsync to trigger. ``` import { useMutation, useQueryClient } from '@tanstack/react-query'; function AddTodo() { const qc = useQueryClient(); const m = useMutation({ mutationFn: (title) => fetch('/api/todos', { method: 'POST', body: title }), onSuccess: () => qc.invalidateQueries({ queryKey: ['todos'] }), }); return <button onClick={() => m.mutate('new')}>Add</button>; } ``` ``` useInfiniteQuery({ queryKey, queryFn, getNextPageParam, initialPageParam }) ``` Cursor/page based infinite loading; exposes fetchNextPage and hasNextPage. ``` const q = useInfiniteQuery({ queryKey: ['feed'], queryFn: ({ pageParam }) => fetchPage(pageParam), initialPageParam: 0, getNextPageParam: (last) => last.nextCursor, }); ``` ``` queryClient.invalidateQueries({ queryKey }) ``` Mark matching queries stale and refetch active ones. ``` queryClient.invalidateQueries({ queryKey: ['todos'] }); ``` ``` queryClient.setQueryData(queryKey, updater) ``` Write data directly into the cache, e.g. for optimistic updates. ``` queryClient.setQueryData(['todos'], (old) => [...old, newTodo]); ``` ``` queryClient.prefetchQuery({ queryKey, queryFn }) ``` Warm the cache before a component renders, e.g. on hover or server-side. ``` await queryClient.prefetchQuery({ queryKey: ['todo', id], queryFn: () => getTodo(id) }); ``` ``` useQueryClient() ``` Access the QueryClient from within components to invalidate, set, or prefetch. ``` const queryClient = useQueryClient(); ``` ## Gotchas - Default staleTime is 0, so queries refetch on mount, window focus, and reconnect; raise staleTime to reduce refetches. - queryFn must throw/reject on failure for isError to trigger; fetch() does not reject on HTTP 4xx/5xx, so check response.ok. - Object query keys are matched structurally and order-sensitively; key serialization is deterministic so put stable values in. - cacheTime was renamed gcTime in v5; v5 also replaced isLoading semantics with isPending for the no-data state. - isFetching is true during background refetches even when data is present; use isPending for the initial no-data load. - Optimistic updates via onMutate need a rollback in onError and a final reconcile in onSettled (invalidate or refetch). - Each useQuery call with the same key shares one cache entry; do not expect independent per-component fetches. - In React 18 strict mode and SSR, create the QueryClient inside a stable ref/useState, not on every render. --- Generated by SkillMake from https://tanstack.com/query/latest/docs/framework/react/overview on 2026-07-02T18:43:37.726Z. Verify against source before relying on details.
File: ~/.claude/skills/tanstack-query/SKILL.md