TanStack Query v5 mit Claude Code: Server State Management 2026

TanStack Query v5 ist der Standard fuer Server State in React — Caching, Background-Refetching, optimistische Updates und Synchronisation. Claude Code kennt alle v5-Breaking-Changes und generiert idiomatischen Code.

useQuery v5: Die neuen Patterns

Queriesv5 API-Aenderungen und Best Practices

# Prompt: "Migriere meine React Query v4 Queries zu TanStack Query v5" // v4 (ALT): const { data, isLoading } = useQuery(['user', userId], () => fetchUser(userId)); // v5 (NEU) — object-only Syntax! const { data, isLoading, isFetching } = useQuery({ queryKey: ['user', userId], queryFn: () => fetchUser(userId), staleTime: 5 * 60 * 1000, // 5 Minuten gcTime: 10 * 60 * 1000, // ehemals cacheTime in v4 enabled: !!userId, // Nur fetchen wenn userId vorhanden placeholderData: keepPreviousData, // v5: importierbar statt keepPreviousData option }); // Query Options Pattern — wiederverwendbar: export const userQueryOptions = (userId: string) => queryOptions({ queryKey: ['user', userId], queryFn: () => fetchUser(userId), staleTime: 60_000, }); // Verwendung in Component + Prefetch: const { data: user } = useQuery(userQueryOptions(userId)); // In Route-Loader (React Router v6): await queryClient.ensureQueryData(userQueryOptions(userId)); // Select: nur relevante Daten abonnieren const { data: userName } = useQuery({ ...userQueryOptions(userId), select: (user) => user.name, // Re-render nur wenn Name sich aendert });
v5 Migration-Tipp: "Migriere alle React Query v4 Hooks zu TanStack Query v5. Erklaere alle Breaking Changes und generiere die neue object-Syntax." Claude Code kennt alle 20+ Breaking Changes von v4 zu v5.

useMutation und Optimistic Updates

MutationsOptimistische Updates und Rollback

# Prompt: "Todo-Liste mit optimistischem Toggle — sofort im UI, Rollback bei Fehler" const toggleTodo = useMutation({ mutationFn: (todoId: string) => updateTodo(todoId, { completed: true }), onMutate: async (todoId) => { // Laufende Refetches stoppen await queryClient.cancelQueries({ queryKey: ['todos'] }); // Snapshot fuer Rollback const prev = queryClient.getQueryData<Todo[]>(['todos']); // Optimistisches Update queryClient.setQueryData<Todo[]>(['todos'], (old) => old?.map(t => t.id === todoId ? { ...t, completed: !t.completed } : t) ?? [] ); return { prev }; // Context fuer onError }, onError: (err, todoId, context) => { // Rollback auf Snapshot queryClient.setQueryData(['todos'], context?.prev); toast.error('Aktualisierung fehlgeschlagen'); }, onSettled: () => { // Immer: echte Daten laden queryClient.invalidateQueries({ queryKey: ['todos'] }); }, }); // v5: mutateAsync fuer await-Verwendung const handleToggle = async (id: string) => { try { await toggleTodo.mutateAsync(id); toast.success('Aktualisiert!'); } catch (e) { // Fehler bereits in onError behandelt } };

Prefetching in Next.js Server Components

PrefetchHydrationBoundary fuer SSR

// app/users/page.tsx — Server Component import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query'; export default async function UsersPage() { const queryClient = new QueryClient(); // Server-seitig prefetchen await queryClient.prefetchQuery({ queryKey: ['users'], queryFn: fetchUsers, // Direkter DB-Call auf Server! }); return ( // Dehydrierter State wird zum Client gesendet <HydrationBoundary state={dehydrate(queryClient)}> <UserList /> {/* Client Component — Cache bereits befuellt */} </HydrationBoundary> ); } // UserList.tsx (Client Component) — kein Loading-State! function UserList() { const { data: users } = useQuery({ queryKey: ['users'], queryFn: fetchUsers, // Vom Server hydratisiert — kein Netzwerk-Call! }); return users?.map(u => <UserCard key={u.id} user={u} />); }

Infinite Queries: Endloser Scroll

InfiniteuseInfiniteQuery fuer Pagination

# Prompt: "Infinite Scroll Feed mit useInfiniteQuery" const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = useInfiniteQuery({ queryKey: ['feed', filter], queryFn: ({ pageParam }) => fetchFeed({ cursor: pageParam, limit: 20, filter }), initialPageParam: undefined as string | undefined, getNextPageParam: (lastPage) => lastPage.nextCursor, // undefined = kein naechste Seite getPreviousPageParam: (firstPage) => firstPage.prevCursor, }); // Alle Posts aus allen Seiten flach: const posts = data?.pages.flatMap(page => page.posts) ?? []; // IntersectionObserver Trigger: const { ref } = useIntersection({ onIntersect: () => { if (hasNextPage) fetchNextPage(); }, }); return ( <div> {posts.map(p => <PostCard key={p.id} post={p} />)} <div ref={ref}>{isFetchingNextPage && <Spinner />}</div> </div> );

Data Fetching im Kurs

Im Claude Code Mastery Kurs: vollstaendiges TanStack Query v5 Modul mit Migration-Guide, Prefetching-Patterns, Optimistic Updates und Infinite Scroll — inkl. Integration mit Next.js Server Components und tRPC.

14 Tage kostenlos testen →