TanStack Query (React Query)
TanStack Query (formerly React Query) manages server state: caching, background refetch, deduplication, pagination, and mutations. It eliminates most manual fetch + useEffect + useState boilerplate.
Queries and Mutations useQuery fetches and caches data keyed by queryKey. Identical keys share cache across components. useMutation handles POST/PUT/DELETE with success/error callbacks and cache invalidation.
Install @tanstack/react-query and wrap app in QueryClientProvider. DevTools optional but invaluable during development.
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>
);
}
function Posts() {
const { data, isLoading } = useQuery({
queryKey: ['posts'],
queryFn: () => fetch('/api/posts').then(r => r.json()),
});
} queryKey uniquely identifies cached data — include all variables that affect the fetch.
Core TanStack Query APIs useQuery({ queryKey, queryFn, staleTime, enabled })
useMutation({ mutationFn, onSuccess })
queryClient.invalidateQueries({ queryKey: ['posts'] }) queryKey arrays should include filter params: ['posts', { page }]. staleTime controls how long data is considered fresh. enabled: false skips fetch until condition true. Invalidate queries after mutations to refresh lists. TanStack Query Reference Essential APIs for React server state.
API Purpose useQuery Fetch + cache read useMutation Create/update/delete queryKey Cache identifier invalidateQueries Mark stale, refetch setQueryData Optimistic cache update prefetchQuery Load before navigation
Designing Query Keys Hierarchical keys enable targeted invalidation: ['posts'] invalidates all post queries; ['posts', id] targets one record.
['posts'] // all posts
['posts', { status: 'draft' }] // filtered
['posts', postId] // single post Mutations and Cache Updates After creating a post, invalidate ['posts'] or optimistically append to cache with setQueryData for instant UI.
const mutation = useMutation({
mutationFn: createPost,
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['posts'] }),
}); Common Mistakes Unstable query keys causing infinite refetches. Storing server data in Redux/Zustand unnecessarily. Not invalidating cache after mutations. Missing QueryClientProvider above consumers. Key Takeaways TanStack Query owns server/async state and caching. useQuery + queryKey replaces most fetch effects. useMutation + invalidation keeps UI in sync after writes. Design hierarchical query keys for flexible cache control.
Pro Tip
Install @tanstack/react-query-devtools during development — visualize cache state and query lifecycles instantly.
Loading and Error States Go to next item