How do you implement state management patterns in React applications?
React state management should match the scope and complexity of the data being managed. Local state: useState for component-specific state (form inputs, UI toggles, local loading states). This is always the first choice; avoid premature global state. Lifted state: when sibling components share state, lift it to their common parent. Keep state as close to where it's used as possible. Context: React Context for state that many components across the tree need (auth state, theme, locale). Avoid putting frequently-changing data in context (causes re-renders of all consumers). For frequently-changing data, use more targeted solutions. External state managers: Zustand (minimal API, no boilerplate, great for medium complexity), Jotai (atomic state model, fine-grained reactivity), TanStack Query (server state management with caching, deduplication, and background refresh), and Redux Toolkit (for complex client state with many reducers and middleware). Server state vs client state: server state (data from APIs) should be managed with TanStack Query or SWR, which handle caching, refetching, optimistic updates, and stale data. Client state (UI state, user preferences) should use simpler tools (useState, Zustand). Pattern: most applications need TanStack Query for server state + useState/Zustand for client state. URL state: use URL parameters for state that should be shareable and bookmarkable (search filters, pagination, selected tabs). Implement with React Router's useSearchParams. Form state: use React Hook Form or Formik for complex forms with validation, or native form handling for simple cases. Performance: use useMemo and useCallback judiciously (only when measured performance issues exist), implement React.memo for expensive pure components, and consider using useTransition for non-urgent state updates.