TanStack Query Cheat Sheet

Quick reference for TanStack Query (React Query): queries, mutations, caching, invalidation, and optimistic updates. Master server state management.

Setup & Basic Queries Query Options Mutations Cache Management Advanced Patterns

Setup & Basic Queries

npm install @tanstack/react-query Install TanStack Query for React
<QueryClientProvider client={new QueryClient()}><App /></QueryClientProvider> Wrap app with QueryClientProvider
const { data, isLoading, error } = useQuery({ queryKey: ["todos"], queryFn: fetchTodos }) Basic query with key and fetch function
const { data } = useQuery({ queryKey: ["todo", id], queryFn: () => fetchTodo(id) }) Query with dynamic key (auto-refetches when id changes)
const { data } = useQuery({ queryKey: ["todos"], queryFn: fetchTodos, enabled: !!userId }) Conditional query — only runs when enabled is true

Query Options

staleTime: 5 * 60 * 1000 Data stays fresh for 5 minutes (no refetch)
gcTime: 30 * 60 * 1000 Garbage collect unused cache after 30 minutes (formerly cacheTime)
refetchInterval: 10000 Auto-refetch every 10 seconds (polling)
retry: 3, retryDelay: (attempt) => attempt * 1000 Retry failed queries 3 times with backoff
select: (data) => data.filter(t => t.done) Transform/select a subset of query data

Mutations

const mutation = useMutation({ mutationFn: createTodo }) Define a mutation with a mutation function
mutation.mutate({ title: "New" }) Trigger the mutation with variables
mutation.mutateAsync({ title: "New" }).then(data => ...) Trigger mutation and get a Promise back
onSuccess: (data, vars, ctx) => queryClient.invalidateQueries({ queryKey: ["todos"] }) Invalidate queries on successful mutation
onError: (err, vars, ctx) => { /* rollback */ }, onSettled: () => { /* always runs */ } Handle mutation error and settled callbacks

Cache Management

queryClient.invalidateQueries({ queryKey: ["todos"] }) Mark queries as stale and trigger refetch
queryClient.setQueryData(["todo", id], updatedTodo) Directly update cached data (optimistic update)
queryClient.getQueryData(["todo", id]) Read cached data without triggering a fetch
queryClient.prefetchQuery({ queryKey: ["todo", id], queryFn: fetchTodo }) Prefetch data before it is needed (e.g., on hover)
queryClient.cancelQueries({ queryKey: ["todos"] }) Cancel in-flight queries (useful before optimistic update)

Advanced Patterns

useInfiniteQuery({ queryKey: ["items"], queryFn: ({ pageParam }) => fetch(pageParam), getNextPageParam: (last) => last.next }) Infinite scroll / load more with pagination
useSuspenseQuery({ queryKey: ["todos"], queryFn: fetchTodos }) Query with React Suspense support (throws promise)
placeholderData: (prev) => prev Keep previous data while refetching (keepPreviousData pattern)
queryClient.setMutationDefaults(["addTodo"], { mutationFn: createTodo, onMutate: async (todo) => { ... } }) Set default mutation options for offline-first optimistic updates
useIsFetching({ queryKey: ["todos"] }) Get number of active fetches (useful for global loading indicators)
Step-by-Step Guide

How to Test an API Online

Read Guide →

More Cheat Sheets