TanStack Query manages the lifecycle of server data: fetch, cache, retry, refresh and invalidate.
Core concepts
- useQuery: Describe data with a
queryKeyand aqueryFn. You get loading, error and data states plus caching and background refresh. — TanStack Query - useMutation: Wrap writes in mutations and invalidate or update related queries on success. Use optimistic updates with rollback for snappy UIs. — TanStack Query
- Query keys: Keys identify cached data. Use arrays like
['items', filters]so changing filters fetches separately and caching works. — TanStack Query - React Native wiring: Hook
onlineManagerto NetInfo andfocusManagerto AppState so queries pause offline and refetch when the app returns to the foreground. — TanStack Query React Native - Offline persistence: Persist the query cache to storage for instant startup and offline reading, with a sensible
maxAgeand a cache-busting key on schema changes. — TanStack Query persist
Concept videos
YouTube channels and searches for these topics. On a large screen they open in the reading panel next to the roadmap.
- TanStack Query tutorials — YouTube search: TanStack Query React Native tutorial
Explanation
Stale time
Data is stale immediately by default. Set staleTime per query to control how often it refetches, balancing freshness against battery and data use.
Error and retry policy
Default retries are fine for transient network errors, but disable them for 4xx errors so users do not wait on requests that cannot succeed.
What Is It?
TanStack Query is an async state manager that caches and synchronises data from servers.
Why Should I Care?
It replaces hand-written loading flags and effect-based fetching that agents often get subtly wrong.
Real World Analogy
It is a courier who keeps a local copy of remote files, knows when a copy is stale, and re-fetches without bothering you.
Visual Mental Model
queryKey -> cache hit? fresh -> return; stale -> return + refetch -> update subscribersSmallest Possible Example
import { useQuery } from '@tanstack/react-query';
export function useItems(filter: string) {
return useQuery({
queryKey: ['items', filter],
queryFn: () => fetch(`/api/items?filter=${filter}`).then((r) => r.json()),
staleTime: 60_000,
});
}Common Mistakes
❌ Using useEffect and useState to fetch.
You lose caching, deduping and retries, and create race conditions.
❌ Query keys that omit variables.
Different filters share one cache entry and show wrong data.
Build This Mini Project
Build a list with filters via useQuery, a create form with an optimistic useMutation, and a pull-to-refresh that calls refetch.
Prompts for Cursor, Claude Code & Codex
Paste these into Cursor, Claude Code, Codex, or any coding agent. Replace the bracketed parts with your app details, and keep the agent in plan mode first so you review the approach before it edits files.
Convert effect fetching
Find components that fetch data with useEffect and useState. Convert them to TanStack Query hooks in hooks/ with proper query keys, loading and error UI, and invalidate after mutations.Rules, databases & blogs to use
- TanStack Query v5 rule: query conventions
- TanStack Query rule: alternate rule

