--- name: jotai-expert description: Expert guidance for Jotai state management in React applications. Provides best practices, performance optimization, and architectural patterns. Use when designing atom structures, implementing state management, optimizing re-renders, handling async state, integrating with TypeScript, or reviewing Jotai code for performance issues. Triggers on tasks involving Jotai atoms, derived state, focusAtom, splitAtom, atomFamily, or state management architecture decisions. --- # Jotai Expert Jotai is a primitive and flexible state management library for React using an atomic approach. Always reference https://jotai.org/ for the latest API details. ## Decision Tree ``` Need state management? ├── Simple local state → useState (no Jotai needed) ├── Shared state across components │ ├── Few components, same tree → Context may suffice │ └── Many components, complex → Use Jotai ✓ └── Global app state → Use Jotai ✓ Choosing atom type: ├── Static value → atom(initialValue) ├── Computed from other atoms → atom((get) => ...) ├── Need to modify other atoms → atom(null, (get, set) => ...) ├── Persist to storage → atomWithStorage() ├── List of items → splitAtom() or atoms-in-atom └── Parameterized data → atomFamily() Performance issue? ├── Component re-renders too often │ ├── Only reading? → useAtomValue │ ├── Only writing? → useSetAtom │ ├── Large object? → selectAtom / focusAtom │ └── List items? → splitAtom └── Async loading states → loadable() or manual loading atoms ``` ## Core Patterns ### Atom Types ```typescript import { atom } from 'jotai' // 1. Primitive: holds value const countAtom = atom(0) // 2. Derived read-only: computed from others const doubleAtom = atom((get) => get(countAtom) * 2) // 3. Derived read-write: custom setter const celsiusAtom = atom(0) const fahrenheitAtom = atom( (get) => get(celsiusAtom) * 9/5 + 32, (get, set, newF: number) => set(celsiusAtom, (newF - 32) * 5/9) ) // 4. Write-only (action): no read value const incrementAtom = atom(null, (get, set) => { set(countAtom, get(countAtom) + 1) }) ``` ### Hook Selection | Need | Hook | Re-renders on change | |------|------|---------------------| | Read only | `useAtomValue(atom)` | Yes | | Write only | `useSetAtom(atom)` | No | | Both | `useAtom(atom)` | Yes | ### Reference Stability ```typescript // ❌ WRONG: Creates new atom every render function Component() { const myAtom = atom(0) // Unstable reference } // ✅ CORRECT: Define outside component const myAtom = atom(0) function Component() { const [value] = useAtom(myAtom) } // ✅ CORRECT: useMemo for dynamic atoms function Component({ id }) { const itemAtom = useMemo(() => atom(items[id]), [id]) } ``` ## Performance Optimization ### 1. Granular Subscriptions ```typescript // ❌ BAD: Re-renders on any user field change function UserProfile() { const [user] = useAtom(userAtom) return