← Back to all products

State Management Patterns

$29

Zustand, Jotai, and React Query patterns for complex state: optimistic updates, caching, and real-time sync.

📁 25 files
JSONMarkdownTypeScriptReact

📄 Product Preview

Try the interactive reader and demo tools below, or get the full product with all content unlocked.

📖 Interactive Reader (Free Preview) ⚙ Try Demo Tools 📦 Download Free Sample

📁 File Structure 25 files

state-management-patterns/ ├── LICENSE ├── README.md ├── examples/ │ ├── dashboard-jotai.tsx │ ├── data-table-react-query.tsx │ └── todo-app-zustand.tsx ├── free-sample.zip ├── guide/ │ └── decision-guide.md ├── guides/ │ └── decision-guide.md ├── index.html ├── src/ │ ├── jotai/ │ │ ├── async-atoms.ts │ │ ├── atom-families.ts │ │ └── atoms.ts │ ├── react-query/ │ │ ├── cache-invalidation.ts │ │ ├── infinite-queries.ts │ │ ├── mutations.ts │ │ └── queries.ts │ ├── realtime/ │ │ ├── optimistic-updates.ts │ │ └── websocket-sync.ts │ └── zustand/ │ ├── middleware.ts │ ├── persistence.ts │ └── store-slices.ts ├── tests/ │ ├── jotai.test.ts │ ├── react-query.test.ts │ └── zustand.test.ts └── tsconfig.json

📖 Documentation Preview README excerpt

State Management Patterns

Battle-tested patterns for managing complex client state in React applications using Zustand, Jotai, and React Query. This collection covers the patterns that emerge when you move beyond simple useState — optimistic updates, cache synchronization, real-time data, and the hard decisions about where state actually belongs.

What's Inside

Zustand Patterns (`src/zustand/`)

  • Store Slices — Split large stores into composable slices that share a single store instance. Includes typed slice creators and cross-slice communication.
  • Middleware Stack — Logging, devtools integration, performance tracking, and immer middleware composed together.
  • Persistence Layer — Storage adapters (localStorage, sessionStorage, IndexedDB) with migration support for evolving store shapes.

Jotai Patterns (`src/jotai/`)

  • Atoms & Derived Atoms — Primitive atoms, computed atoms with selectors, and write-only atoms for complex updates.
  • Async Atoms — Data fetching atoms with loading/error states, retry logic, and Suspense integration.
  • Atom Families — Parameterized atoms for managing collections (e.g., per-item expanded state, per-tab filters).

React Query Patterns (`src/react-query/`)

  • Query Patterns — Dependent queries, parallel queries, conditional fetching, and placeholder/initial data strategies.
  • Mutations & Optimistic Updates — Mutation patterns with rollback, optimistic list updates, and toast notifications on failure.
  • Infinite Queries — Cursor-based and offset-based infinite scroll with bi-directional support.
  • Cache Invalidation — Granular invalidation, cache seeding from mutations, and stale-while-revalidate strategies.

Real-Time Sync (`src/realtime/`)

  • WebSocket Integration — Reconnecting WebSocket manager that syncs server events into Zustand and React Query caches.
  • Optimistic Updates — Shared patterns for optimistic UI across all three libraries, with server reconciliation.

Decision Guide (`guides/decision-guide.md`)

When should you reach for Zustand vs. Jotai vs. React Query? A decision tree based on the _shape_ of your state problem, not library popularity.

Working Examples (`examples/`)

  • Todo app with Zustand (local-first with sync)
  • Dashboard with Jotai (fine-grained reactivity)
  • Data table with React Query (server state with filtering)

Quick Start


# Install the libraries you want to use (pick one or combine):
npm install zustand immer
npm install jotai
npm install @tanstack/react-query

# Copy the patterns you need into your project
cp -r src/zustand/ your-project/src/state/

Each pattern file is self-contained. Import what you need, ignore the rest.

File Structure


state-management-patterns/
├── README.md
├── LICENSE
├── tsconfig.json
├── src/
│   ├── zustand/
│   │   ├── store-slices.ts           # Composable store slices
│   │   ├── middleware.ts             # Custom middleware stack
│   │   └── persistence.ts           # Storage adapters & migrations

*... continues with setup instructions, usage examples, and more.*

📄 Code Sample .tsx preview

examples/dashboard-jotai.tsx// ============================================================================ // Example: Dashboard with Jotai (Fine-Grained Reactivity) // ============================================================================ // // A dashboard that shows why Jotai excels at fine-grained updates. // Each widget subscribes to only the atoms it needs, so updating one // metric doesn't re-render the entire dashboard. // // ============================================================================ import React, { useEffect } from "react"; import { atom, useAtom, useAtomValue, useSetAtom } from "jotai"; import { atomWithStorage } from "jotai/utils"; // --------------------------------------------------------------------------- // Dashboard atoms — each metric is an independent atom // --------------------------------------------------------------------------- // Individual metrics — updating revenue doesn't re-render the users widget const revenueAtom = atom<number>(0); const activeUsersAtom = atom<number>(0); const conversionRateAtom = atom<number>(0); const errorRateAtom = atom<number>(0); // Historical data for sparkline charts const revenueHistoryAtom = atom<number[]>([]); const usersHistoryAtom = atom<number[]>([]); // Dashboard settings — persisted to localStorage const refreshIntervalAtom = atomWithStorage<number>("dashboard-refresh", 5000); const dashboardLayoutAtom = atomWithStorage<"grid" | "list">("dashboard-layout", "grid"); // Derived atoms — computed from individual metrics const healthScoreAtom = atom<number>((get) => { const errorRate = get(errorRateAtom); const conversion = get(conversionRateAtom); // Health score: 100 = perfect, decreases with errors, increases with conversion return Math.max(0, Math.min(100, Math.round(100 - errorRate * 10 + conversion))); });
Buy Now — $29 Back to Products