Jotai mit Claude Code: Atomares State Management 2026

Jotai verfolgt einen Bottom-Up-Ansatz für React State — einzelne Atoms die sich zu komplexem State zusammensetzen. Claude Code kennt alle Jotai-Patterns: Atoms, Derived Atoms, Async Atoms und die mächtigen Utility-Atoms.

Atoms: Das Grundprinzip

AtomsPrimitive und Derived Atoms

# Prompt: "State-Architektur für einen Warenkorb mit Jotai" import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai'; // Primitive Atoms — minimale State-Einheiten const cartItemsAtom = atom<CartItem[]>([]); const couponCodeAtom = atom<string | null>(null); const currencyAtom = atom<'EUR' | 'USD'>('EUR'); // Derived Atom — berechnet sich aus anderen Atoms const cartTotalAtom = atom(async (get) => { const items = get(cartItemsAtom); const coupon = get(couponCodeAtom); const subtotal = items.reduce((sum, item) => sum + item.price * item.qty, 0); if (coupon) { const discount = await fetchDiscount(coupon); // Async OK! return subtotal * (1 - discount); } return subtotal; }); // Write-only Atom — Action Pattern const addToCartAtom = atom( null, // Read-Wert (null = write-only) (get, set, product: Product) => { const items = get(cartItemsAtom); const existing = items.find(i => i.id === product.id); if (existing) { set(cartItemsAtom, items.map(i => i.id === product.id ? { ...i, qty: i.qty + 1 } : i )); } else { set(cartItemsAtom, [...items, { ...product, qty: 1 }]); } } ); // In Komponenten: function CartButton({ product }) { const addToCart = useSetAtom(addToCartAtom); // Kein Re-render bei State-Änderungen! return <button onClick={() => addToCart(product)}>In den Warenkorb</button>; }

Async Atoms mit Suspense

AsyncDaten laden ohne useState/useEffect

# Prompt: "User-Daten mit Jotai laden, mit Suspense und Error Boundary" // Async Atom — integriert sich in React Suspense const userAtom = atom(async () => { const res = await fetch('/api/user/me'); if (!res.ok) throw new Error('Failed to load user'); return res.json() as Promise<User>; }); // atomFamily: Atom pro Parameter (z.B. pro userId) import { atomFamily } from 'jotai/utils'; const postAtomFamily = atomFamily((postId: string) => atom(async () => { const res = await fetch(`/api/posts/${postId}`); return res.json() as Promise<Post>; }) ); // Verwendung mit Suspense: function UserProfile() { const user = useAtomValue(userAtom); // Suspense löst auf! return <div>{user.name}</div>; } function App() { return ( <ErrorBoundary fallback={<Error />}> <Suspense fallback={<Skeleton />}> <UserProfile /> </Suspense> </ErrorBoundary> ); }
Suspense-Tipp: "Refaktoriere diesen useEffect+useState-Block in einen Jotai Async Atom mit Suspense." Claude Code erkennt das Pattern sofort und schreibt typsichers, boilerplate-freies Code.

Utility Atoms: Storage, Reset, Reducer

UtilsatomWithStorage, atomWithReducer, atomWithReset

# Prompt: "Theme-Präferenz und Filter-State persistent speichern" import { atomWithStorage, atomWithReset, atomWithReducer } from 'jotai/utils'; // Persistiert in localStorage automatisch const themeAtom = atomWithStorage<'light' | 'dark'>('theme', 'light'); const sidebarOpenAtom = atomWithStorage('sidebar', true); // Reset auf Default-Wert const searchAtom = atomWithReset(''); import { useResetAtom } from 'jotai/utils'; function SearchBar() { const [search, setSearch] = useAtom(searchAtom); const reset = useResetAtom(searchAtom); return ( <> <input value={search} onChange={e => setSearch(e.target.value)} /> <button onClick={reset}>Löschen</button> </> ); } // Reducer-Pattern (wie useReducer aber global) type FilterAction = | { type: 'SET_CATEGORY'; payload: string } | { type: 'RESET' }; const filterAtom = atomWithReducer( { category: 'all', sortBy: 'date' }, (state, action: FilterAction) => { switch (action.type) { case 'SET_CATEGORY': return { ...state, category: action.payload }; case 'RESET': return { category: 'all', sortBy: 'date' }; default: return state; } } );

Performance: Nur relevante Re-renders

PerformanceGranulare Subscriptions

# Jotai vs. Context — warum Jotai performanter ist // ❌ React Context: jede Änderung rendert ALLE Consumer const AppContext = createContext({ user: null, cart: [], theme: 'light' }); // Wenn cart sich ändert → user-Komponenten rendern auch! // ✅ Jotai: jede Komponente subscribed nur auf IHR Atom const userAtom = atom<User | null>(null); const cartAtom = atom<CartItem[]>([]); const themeAtom = atomWithStorage('theme', 'light'); function UserName() { const user = useAtomValue(userAtom); // Rendert NUR wenn userAtom sich ändert // Cart-Änderungen = KEIN Re-render hier return <span>{user?.name}</span>; } # Selector-Atom für weitere Granularität: const cartCountAtom = atom((get) => get(cartAtom).length); // Rendert nur wenn Anzahl sich ändert — nicht wenn Preise sich ändern!

State Management im Kurs

Im Claude Code Mastery Kurs: vollständiges Jotai-Modul mit Atom-Patterns, Async-Integration, Utility-Atoms und Performance-Optimierung — inkl. Vergleich mit Zustand und Redux Toolkit für verschiedene Use-Cases.

14 Tage kostenlos testen →