Skip to main content

tanstack-query

TanStack Query v5 (React Query) server state management. Use for data fetching, caching, mutations, or encountering v4 migration, stale data, invalidation errors.

Quellinformationen

Repository
secondsky/claude-skills
Letzte Quellaktivität
5. August 2026 um 23:44
Erkannte Sprache von SKILL.md
Englisch
Sterne
231
Forks
32

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
34 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
tanstack-query
description
TanStack Query v5 (React Query) server state management. Use for data fetching, caching, mutations, or encountering v4 migration, stale data, invalidation errors.
metadata
{"keywords":["TanStack Query","React Query","useQuery","useMutation","useInfiniteQuery","useSuspenseQuery","QueryClient","QueryClientProvider","data fetching","server state","caching","staleTime","gcTime","query invalidation","prefetching","optimistic updates","mutations","query keys","query functions","error boundaries","suspense","React Query DevTools","v5 migration","v4 to v5","request waterfalls","background refetching","cacheTime renamed","loading status renamed","pending status","initialPageParam required","keepPreviousData removed","placeholderData","[Truncated]"]}
license
MIT
# TanStack Query (React Query) v5 **Status**: Production Ready ✅ **Last Updated**: 2026-08-03 **Dependencies**: React 18.0+ (18.3+ recommended), TypeScript 4.9+ (5.x preferred) **Latest Versions**: @tanstack/react-query@5.101.4, @tanstack/react-query-devtools@5.101.4, @tanstack/eslint-plugin-query@5.101.4 --- ## Quick Start (5 Minutes) ### 1. Install Dependencies ```bash # choose your package manager pnpm add @tanstack/react-query@latest @tanstack/react-query-devtools@latest # or npm install @tanstack/react-query@latest @tanstack/react-query-devtools@latest # or bun add @tanstack/react-query@latest @tanstack/react-query-devtools@latest ``` **Why this matters:** - TanStack Query v5 requires React 18+ (uses useSyncExternalStore) - DevTools are essential for debugging queries and mutations - v5 has breaking changes from v4 - use latest for all fixes ### 2. Set Up QueryClient Provider ```tsx // src/main.tsx or src/index.tsx import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' import App from './App' // Create a client const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 1000 * 60 * 5, // 5 minutes gcTime: 1000 * 60 * 60, // 1 hour (formerly cacheTime) retry: 1, refetchOnWindowFocus: false, }, }, }) createRoot(document.getElementById('root')!).render( <StrictMode> <QueryClientProvider client={queryClient}> <App /> <ReactQueryDevtools initialIsOpen={false} /> </QueryClientProvider> </StrictMode> ) ``` **CRITICAL:** - Wrap entire app with `QueryClientProvider` - Configure `staleTime` to avoid excessive refetches (default is 0) - Use `gcTime` (not `cacheTime` - renamed in v5) - DevTools should be inside provider **Know the defaults (v5):** - `staleTime: 0` → data is immediately stale, so refetches on mount/focus unless you raise it - `gcTime: 5 * 60 * 1000` → inactive data is garbage-collected after 5 minutes - `retry: 3` in browsers, `retry: 0` on the server - `refetchOnWindowFocus: true` and `refetchOnReconnect: true` - `networkMode: 'online'` (requests pause while offline). Switch to `'always'` for SSR/prefetch where you don't want cancellation. citeturn1search0turn1search1 ### 3. Create First Query ```tsx // src/hooks/useTodos.ts import { useQuery } from '@tanstack/react-query' type Todo = { id: number title: string completed: boolean } async function fetchTodos(): Promise<Todo[]> { const response = await fetch('/api/todos') if (!response.ok) { throw new Error('Failed to fetch todos') } return response.json() } export function useTodos() { return useQuery({ queryKey: ['todos'], queryFn: fetchTodos, }) } // Usage in component: function TodoList() { const { data, isPending, isError, error } = useTodos() if (isPending) return <div>Loading...</div> if (isError) return <div>Error: {error.message}</div> return ( <ul> {data.map(todo => ( <li key={todo.id}>{todo.title}</li> ))} </ul> ) } ``` **CRITICAL:** - v5 requires object syntax: `useQuery({ queryKey, queryFn })` - Use `isPending` (not `isLoading` - that now means "pending AND fetching") - Always throw errors in queryFn for proper error handling - QueryKey should be array for consistent cache keys ### 4. Create First Mutation ```tsx // src/hooks/useAddTodo.ts import { useMutation, useQueryClient } from '@tanstack/react-query' type NewTodo = { title: string } async function addTodo(newTodo: NewTodo) { const response = await fetch('/api/todos', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newTodo), }) if (!response.ok) throw new Error('Failed to add todo') return response.json() } export function useAddTodo() { const queryClient = useQueryClient() return useMutation({ mutationFn: addTodo, onSuccess: () => { // Invalidate and refetch todos queryClient.invalidateQueries({ queryKey: ['todos'] }) }, }) } // Usage in component: function AddTodoForm() { const { mutate, isPending } = useAddTodo() const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault() const formData = new FormData(e.currentTarget) mutate({ title: formData.get('title') as string }) } return ( <form onSubmit={handleSubmit}> <input name="title" required /> <button type="submit" disabled={isPending}> {isPending ? 'Adding...' : 'Add Todo'} </button> </form> ) } ``` **Why this works:** - Mutations use callbacks (`onSuccess`, `onError`, `onSettled`) - queries don't - `invalidateQueries` triggers background refetch - Mutations don't cache by default (correct behavior) --- ## The 7-Step Setup Process ### Step 1: Install Dependencies ```bash # Core library (required) pnpm add @tanstack/react-query # DevTools (highly recommended for development) pnpm add -D @tanstack/react-query-devtools # Optional: ESLint plugin for best practices pnpm add -D @tanstack/eslint-plugin-query ``` **Package roles:** - `@tanstack/react-query` - Core React hooks and QueryClient - `@tanstack/react-query-devtools` - Visual debugger (dev only, tree-shakeable) - `@tanstack/eslint-plugin-query` - Catches common mistakes **Version requirements:** - React 18.0 or higher (uses `useSyncExternalStore`) - TypeScript 5.2+ for best type inference (optional but recommended) ### Step 2: Configure QueryClient ```tsx // src/lib/query-client.ts import { QueryClient } from '@tanstack/react-query' export const queryClient = new QueryClient({ defaultOptions: { queries: { // How long data is considered fresh (won't refetch during this time) staleTime: 1000 * 60 * 5, // 5 minutes // How long inactive data stays in cache before garbage collection gcTime: 1000 * 60 * 60, // 1 hour (v5: renamed from cacheTime) // Retry failed requests (0 on server, 3 on client by default) retry: (failureCount, error) => { if (error instanceof Response && error.status === 404) return false return failureCount < 3 }, // Refetch on window focus (can be annoying during dev) refetchOnWindowFocus: false, // Refetch on network reconnect refetchOnReconnect: true, // Refetch on component mount if data is stale refetchOnMount: true, }, mutations: { // Retry mutations on failure (usually don't want this) retry: 0, }, }, }) ``` **Key configuration decisions:** **staleTime vs gcTime:** - `staleTime`: How long until data is considered "stale" and might refetch - `0` (default): Data is immediately stale, refetches on mount/focus - `1000 * 60 * 5`: Data fresh for 5 min, no refetch during this time - `Infinity`: Data never stale, manual invalidation only - `gcTime`: How long unused data stays in cache - `1000 * 60 * 5` (default): 5 minutes - `Infinity`: Never garbage collect (memory leak risk) **When to refetch:** - `refetchOnWindowFocus: true` - Good for frequently changing data (stock prices) - `refetchOnWindowFocus: false` - Good for stable data or during development - `refetchOnMount: true` - Ensures fresh data when component mounts - `refetchOnReconnect: true` - Refetch after network reconnect ### Step 3: Wrap App with Provider ```tsx // src/main.tsx import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import { QueryClientProvider } from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' import { queryClient } from './lib/query-client' import App from './App' createRoot(document.getElementById('root')!).render( <StrictMode> <QueryClientProvider client={queryClient}> <App /> <ReactQueryDevtools initialIsOpen={false} buttonPosition="bottom-right" /> </QueryClientProvider> </StrictMode> ) ``` **Provider placement:** - Must wrap all components that use TanStack Query hooks - DevTools must be inside provider - Only one QueryClient instance for entire app **DevTools configuration:** - `initialIsOpen={false}` - Collapsed by default - `buttonPosition="bottom-right"` - Where to show toggle button - Automatically removed in production builds (tree-shaken) ### Advanced Setup (Steps 4-7) **For detailed patterns**: Load `references/advanced-setup.md` when implementing custom query hooks, mutations with optimistic updates, DevTools configuration, or error boundaries. **Quick summaries:** **Step 4: Custom Query Hooks** - Use `queryOptions` factory for reusable patterns. Create custom hooks that encapsulate API calls. **Step 5: Mutations** - Use `useMutation` with `onSuccess` to invalidate queries. For instant UI feedback, implement optimistic updates with `onMutate`/`onError`/`onSettled` pattern. **Step 6: DevTools** - Already included in Step 3. Advanced options for customization available in reference. **Step 7: Error Boundaries** - Use `QueryErrorResetBoundary` with React Error Boundary. Configure `throwOnError` option for global vs local error handling. --- ## Critical Rules ### Always Do ✅ **Use object syntax for all hooks** ```tsx // v5 ONLY supports this: useQuery({ queryKey, queryFn, ...options }) useMutation({ mutationFn, ...options }) ``` ✅ **Use array query keys** ```tsx queryKey: ['todos'] // List queryKey: ['todos', id] // Detail queryKey: ['todos', { filter }] // Filtered ``` ✅ **Configure staleTime appropriately** ```tsx staleTime: 1000 * 60 * 5 // 5 min - prevents excessive refetches ``` ✅ **Use isPending for initial loading state** ```tsx if (isPending) return <Loading /> // isPending = no data yet AND fetching ``` ✅ **Throw errors in queryFn** ```tsx if (!response.ok) throw new Error('Failed') ``` ✅ **Invalidate queries after mutations** ```tsx onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['todos'] }) } ``` ✅ **Use queryOptions factory for reusable patterns** ```tsx const opts = queryOptions({ queryKey, queryFn }) useQuery(opts) useSuspenseQuery(opts) prefetchQuery(opts) ``` ✅ **Use gcTime (not cacheTime)** ```tsx gcTime: 1000 * 60 * 60 // 1 hour ``` ✅ **Know your status flags** ```tsx isPending // no data yet, fetch in flight isFetching // any fetch in flight (including refetch) isRefetching // refetch specifically (data already cached) isLoadingError // initial load failed isPaused // networkMode paused (e.g., offline) isFetchingNextPage // useInfiniteQuery loading more ``` ### Never Do ❌ **Never use v4 array/function syntax** ```tsx // v4 (removed in v5): useQuery(['todos'], fetchTodos, options) // ❌ // v5 (correct): useQuery({ queryKey: ['todos'], queryFn: fetchTodos }) // ✅ ``` ❌ **Never use query callbacks (onSuccess, onError, onSettled in queries)** ```tsx // v5 removed these from queries: useQuery({ queryKey: ['todos'], queryFn: fetchTodos, onSuccess: (data) => {}, // ❌ Removed in v5 }) // Use useEffect instead: const { data } = useQuery({ queryKey: ['todos'], queryFn: fetchTodos }) useEffect(() => { if (data) { // Do something } }, [data]) // Or use mutation callbacks (still supported): useMutation({ mutationFn: addTodo, onSuccess: () => {}, // ✅ Still works for mutations }) ``` ❌ **Never use deprecated options** ```tsx // Deprecated in v5: cacheTime: 1000 // ❌ Use gcTime instead isLoading: true // ❌ Meaning changed, use isPending keepPreviousData: true // ❌ Use placeholderData instead onSuccess: () => {} // ❌ Removed from queries useErrorBoundary: true // ❌ Use throwOnError instead ``` ❌ **Never assume isLoading means "no data yet"** ```tsx // v5 changed this: isLoading = isPending && isFetching // ❌ Now means "pending AND fetching" isPending = no data yet // ✅ Use this for initial load ``` ❌ **Never forget initialPageParam for infinite queries**
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen