Zustand mit Claude Code: React State Management ohne Boilerplate 2026

Zustand ist die modernste State-Management-Lösung für React — minimale API, TypeScript-first, kein Provider-Hell. Claude Code kennt alle Zustand-Patterns: Typed Stores, Slices, Middleware und Performance-Optimierung.

Wer React-Apps mit globalem State entwickelt, kennt das Problem: Redux erfordert Actions, Reducers, Selectors und tonnenweise Boilerplate. Context API skaliert schlecht. Recoil und Jotai haben ihre eigenen Quirks. Zustand löst das anders — mit einer simplen, aber mächtigen API, die sich in wenigen Zeilen erklärt.

Claude Code hat Zustand vollständig verinnerlicht. Es generiert typisierte Stores, erkennt Anti-Patterns, schlägt das richtige Slice-Design vor und fügt Middleware korrekt ein — ohne dass du Stack-Overflow-Artikel durchsuchen musst.

Warum Zustand 2026 der Standard ist

Zustand hat sich seit 2022 als De-facto-Standard für mittlere React-Projekte etabliert. Die Kernvorteile:

  • Kein Provider: Store einfach importieren, fertig. Kein <Provider> um die App wickeln.
  • TypeScript-first: Volle Typsicherheit ohne Extra-Konfiguration.
  • Minimale API: Ein Hook, ein Store. Das war's.
  • Flexible Middleware: persist, devtools, immer — alles modular zuschaltbar.
  • Kein Re-render-Problem: Subscriptions sind granular — nur was sich ändert, rendert neu.
Bundle-Größe 2026: Zustand wiegt ~2.9 KB (gzipped) — Redux Toolkit kommt auf ~16 KB. Bei identischer Funktionalität ist das ein klarer Vorteil für Performance-sensitive Apps.

1. Typed Store erstellen — der Einstieg mit Claude Code

Der schnellste Weg zu einem produktionsreifen Zustand-Store: Claude Code den Store-Typ beschreiben und generieren lassen.

Claude Code Prompt

"Erstelle einen Zustand-Store für eine E-Commerce-App: Warenkorb mit Produkten (id, name, price, quantity), Methoden addItem, removeItem, updateQuantity, clearCart. TypeScript, volle Typisierung, Selector für Gesamtpreis."

STORE useCartStore.ts — Typed mit Actions

import { create } from 'zustand' // Typen definieren interface CartItem { id: string name: string price: number quantity: number } interface CartStore { items: CartItem[] // Actions addItem: (product: Omit<CartItem, 'quantity'>) => void removeItem: (id: string) => void updateQuantity: (id: string, quantity: number) => void clearCart: () => void // Selectors getTotalPrice: () => number getItemCount: () => number } export const useCartStore = create<CartStore>()((set, get) => ({ items: [], addItem: (product) => set((state) => { const existing = state.items.find((i) => i.id === product.id) if (existing) { return { items: state.items.map((i) => i.id === product.id ? { ...i, quantity: i.quantity + 1 } : i ), } } return { items: [...state.items, { ...product, quantity: 1 }] } }), removeItem: (id) => set((state) => ({ items: state.items.filter((i) => i.id !== id), })), updateQuantity: (id, quantity) => set((state) => ({ items: quantity === 0 ? state.items.filter((i) => i.id !== id) : state.items.map((i) => i.id === id ? { ...i, quantity } : i ), })), clearCart: () => set({ items: [] }), getTotalPrice: () => get().items.reduce((sum, item) => sum + item.price * item.quantity, 0), getItemCount: () => get().items.reduce((sum, item) => sum + item.quantity, 0), }))

Im Component nutzt du den Store ganz ohne Provider:

// CartButton.tsx — kein Context, kein Provider nötig import { useCartStore } from './stores/useCartStore' export function CartButton() { // Granulares Selector-Pattern: nur re-rendern wenn sich count ändert const count = useCartStore((state) => state.getItemCount()) const addItem = useCartStore((state) => state.addItem) return ( <button onClick={() => addItem({ id: 'p1', name: 'Produkt', price: 9.99 })}> Warenkorb ({count}) </button> ) }

2. Slices Pattern für große Apps

Ab einer gewissen App-Größe wird ein einziger monolithischer Store unübersichtlich. Das Slices Pattern teilt den Store in thematische Einheiten auf, die dann kombiniert werden.

Claude Code Prompt

"Refaktoriere den Store in separate Slices: authSlice (user, login, logout), cartSlice (items, addItem, clearCart), uiSlice (modal, toast, loading). Kombiniere sie in einem Root-Store mit TypeScript."

SLICES Slices-Architektur für skalierbare Apps

// stores/slices/authSlice.ts import { StateCreator } from 'zustand' interface User { id: string; email: string; name: string } export interface AuthSlice { user: User | null isAuthenticated: boolean login: (user: User) => void logout: () => void } export const createAuthSlice: StateCreator<AuthSlice> = (set) => ({ user: null, isAuthenticated: false, login: (user) => set({ user, isAuthenticated: true }), logout: () => set({ user: null, isAuthenticated: false }), }) // stores/slices/uiSlice.ts export interface UiSlice { modalOpen: boolean toastMessage: string | null isLoading: boolean openModal: () => void closeModal: () => void showToast: (msg: string) => void setLoading: (v: boolean) => void } export const createUiSlice: StateCreator<UiSlice> = (set) => ({ modalOpen: false, toastMessage: null, isLoading: false, openModal: () => set({ modalOpen: true }), closeModal: () => set({ modalOpen: false }), showToast: (msg) => set({ toastMessage: msg }), setLoading: (v) => set({ isLoading: v }), }) // stores/useStore.ts — Root Store kombiniert alle Slices import { create } from 'zustand' import { createAuthSlice, AuthSlice } from './slices/authSlice' import { createUiSlice, UiSlice } from './slices/uiSlice' import { createCartSlice, CartSlice } from './slices/cartSlice' type RootStore = AuthSlice & UiSlice & CartSlice export const useStore = create<RootStore>()((...a) => ({ ...createAuthSlice(...a), ...createUiSlice(...a), ...createCartSlice(...a), }))
Slice-Kommunikation: Slices können aufeinander zugreifen — der StateCreator-Typ kann auf den kombinierten Root-Store zeigen: StateCreator<RootStore, [], [], AuthSlice>. Claude Code generiert das auf Anfrage automatisch korrekt.

3. Middleware: persist, devtools, immer

Zustand's Middleware-System ist composable — du stapelst Middlewares wie Lego-Steine. Claude Code kennt die korrekte Reihenfolge und Konfiguration.

MIDDLEWARE persist + devtools + immer kombiniert

import { create } from 'zustand' import { persist, devtools } from 'zustand/middleware' import { immer } from 'zustand/middleware/immer' interface SettingsStore { theme: 'light' | 'dark' language: string notifications: { email: boolean; push: boolean } setTheme: (theme: 'light' | 'dark') => void toggleEmailNotification: () => void } export const useSettingsStore = create<SettingsStore>()( devtools( persist( immer((set) => ({ theme: 'light', language: 'de', notifications: { email: true, push: false }, setTheme: (theme) => set((state) => { state.theme = theme // immer: direkte Mutation erlaubt! }), toggleEmailNotification: () => set((state) => { // immer macht nested Updates trivial state.notifications.email = !state.notifications.email }), })), { name: 'user-settings', // localStorage key partialize: (state) => ({ // Nur bestimmte Felder persistieren theme: state.theme, language: state.language, }), } ), { name: 'SettingsStore' } // DevTools-Label ) )

Middleware-Reihenfolge erklärt:

  • devtools — außen: instrumentiert den gesamten Store für Redux DevTools
  • persist — mitte: speichert/lädt aus localStorage oder sessionStorage
  • immer — innen: erlaubt direkte Mutationen im State (kein Spread nötig)
Claude Code Prompt

"Füge dem bestehenden Store persist-Middleware hinzu, aber persistiere nur theme und language — nicht den kompletten State. Nutze sessionStorage statt localStorage."

// sessionStorage statt localStorage persist( immer((set) => ({ /* ... */ })), { name: 'session-settings', storage: createJSONStorage(() => sessionStorage), partialize: (state) => ({ theme: state.theme, language: state.language, }), } )

4. Zustand vs Redux vs Context API — der ehrliche Vergleich 2026

VERGLEICH State Management Optionen im Überblick

Kriterium Zustand Redux Toolkit Context API
Setup-Aufwand Minimal Hoch Minimal
Boilerplate Sehr wenig Viel Mittel
TypeScript-Support Exzellent Gut Manuell
Performance (große Apps) Sehr gut Sehr gut Schlecht
DevTools Redux DevTools Redux DevTools Keine
Middleware-Ökosystem persist, immer, devtools Sehr groß Keines
Bundle-Größe ~2.9 KB ~16 KB 0 KB (built-in)
Lernkurve Flach Steil Flach
Skalierbarkeit Gut (Slices) Exzellent Begrenzt
Async Actions Manuell / React Query RTK Query built-in Manuell

Empfehlung für 2026:

  • Kleine bis mittlere Apps: Zustand — perfekte Balance aus Einfachheit und Power
  • Enterprise-Apps mit komplexem Async: Redux Toolkit + RTK Query
  • Einfaches Theme/Locale Sharing: Context API reicht aus
  • Server State: TanStack Query (unabhängig von der Client-State-Wahl)
Kombination ist erlaubt: Zustand für Client-State + TanStack Query für Server-State ist 2026 der bevorzugte Stack. Claude Code kennt dieses Pattern und kann beide Bibliotheken koordiniert einsetzen.

5. Performance-Optimierung: Selectors richtig nutzen

Ein häufiges Anti-Pattern ist das direkte Destructuring des gesamten Stores. Das triggert Re-renders bei jeder State-Änderung.

PERFORMANCE Granulare Selectors vs. vollständiger Store

// ❌ FALSCH: Re-render bei JEDER Store-Änderung function BadComponent() { const store = useCartStore() // ganzen Store subscriben! return <div>{store.items.length}</div> } // ✅ RICHTIG: Nur re-rendern wenn items.length sich ändert function GoodComponent() { const count = useCartStore((state) => state.items.length) return <div>{count}</div> } // ✅ Mehrere Werte mit useShallow (verhindert unnötige Re-renders) import { useShallow } from 'zustand/react/shallow' function CartSummary() { const { items, getTotalPrice } = useCartStore( useShallow((state) => ({ items: state.items, getTotalPrice: state.getTotalPrice, })) ) return <div>{items.length} Artikel — {getTotalPrice().toFixed(2)} €</div> } // ✅ Computed Values mit memoisierten Selectors (für teure Berechnungen) import { useMemo } from 'react' function ExpensiveComponent() { const items = useCartStore((state) => state.items) const grouped = useMemo( () => items.reduce((acc, item) => { acc[item.id] = (acc[item.id] || 0) + item.quantity return acc }, {} as Record<string, number>), [items] ) return <pre>{JSON.stringify(grouped, null, 2)}</pre> }

6. Claude Code Prompts für Store-Design

Der größte Zeitgewinn entsteht beim initialen Store-Design. Hier sind die effektivsten Prompts:

PROMPTS Bewährte Claude Code Prompt-Patterns

Store aus Interface generieren

"Gegeben dieses TypeScript-Interface, erstelle einen vollständigen Zustand-Store mit sinnvollen Actions und Selectors. Füge persist-Middleware hinzu, persistiere aber nur [Felder]. Erkläre jede Design-Entscheidung kurz."

Store-Review und Optimierung

"Review diesen Zustand-Store auf Anti-Patterns: unnötige Re-renders, fehlende Typen, falsche Middleware-Reihenfolge, Selector-Performance. Schlage konkrete Verbesserungen vor."

Migration von Redux zu Zustand

"Migriere diesen Redux Slice zu Zustand. Behalte alle Typen, ersetze Actions/Reducers durch direktes setState, und behalte die DevTools-Integration. Zeige vorher/nachher."

Async Actions mit Error Handling

"Füge dem Store async Actions hinzu: fetchUser() mit loading/error State, Retry-Logik bei Netzwerkfehlern, und automatisches Token-Refresh. Nutze TanStack Query für das Caching."

7. Async Actions und Loading States

Zustand hat kein eingebautes Konzept für Async — das ist gleichzeitig Stärke (Flexibilität) und Aufgabe (du musst es selbst bauen). Claude Code hat dafür ein bewährtes Pattern:

interface UserStore { user: User | null isLoading: boolean error: string | null fetchUser: (id: string) => Promise<void> } export const useUserStore = create<UserStore>()((set) => ({ user: null, isLoading: false, error: null, fetchUser: async (id) => { set({ isLoading: true, error: null }) try { const res = await fetch(`/api/users/${id}`) if (!res.ok) throw new Error(`HTTP ${res.status}`) const user = await res.json() set({ user, isLoading: false }) } catch (err) { set({ error: err instanceof Error ? err.message : 'Unbekannter Fehler', isLoading: false, }) } }, }))
Empfehlung für Server State: Verwende TanStack Query (React Query) für Datenabruf, Caching und Synchronisation. Zustand eignet sich für Client State (UI-State, User-Präferenzen, lokale Formulare). Diese Trennung reduziert Komplexität erheblich.

Fazit: Zustand + Claude Code = maximale Produktivität

Zustand hat den Sweet Spot getroffen: mächtig genug für echte Apps, simpel genug um in 30 Minuten produktiv zu sein. Mit Claude Code als State-Management-Experten entstehen typisierte, production-ready Stores in Minuten statt Stunden.

Die Kombination funktioniert besonders gut weil:

  • Claude Code die Zustand-API vollständig kennt und korrekte TypeScript-Typen generiert
  • Middleware-Konfigurationen (persist, devtools, immer) korrekt gestapelt werden
  • Anti-Patterns (Selector-Fehler, Re-render-Probleme) direkt erkannt und behoben werden
  • Das Slices-Pattern für große Apps automatisch angewendet wird

State-Management-Modul im Kurs

Im Claude Code Mastery Kurs: vollständiges State-Management-Modul mit Zustand, TanStack Query, Context-Patterns und Performance-Optimierung — für moderne React-Apps ohne Boilerplate.

14 Tage kostenlos testen →