Step 12
Step 12 — Separate server state, UI state, and local data
0 views
Table of contents
Before choosing a state library, identify who owns each value and how long it lives. Copying one value into the URL, React state, a global store, and a cache creates several competing sources of truth.
Split state into four kinds
| State | Source of truth | Suitable location | Example |
|---|---|---|---|
| URL state | Address | Search params | Query, filter, page |
| UI state | Current view | Component state or Zustand | Open panel, selected tab |
| Server state | API and database | TanStack Query | Lists, details, mutation results |
| Offline data | Current device | IndexedDB | Drafts, large models |
Do not copy a server-backed list into Zustand. Let TanStack Query keys express API resource boundaries, then invalidate only affected keys after a successful mutation. Use Zustand for small UI state shared across views, with selectors that avoid unrelated renders.
IndexedDB is a database, not a magic cache
IndexedDB needs versions and migrations. Record size, expiry, and schema version when writing, then validate again when reading. The online API must remain a fallback when the browser reclaims storage or an upgrade fails. Never keep the only copy of user-owned data in IndexedDB.
Read boundary
URL → query key → API response → interface
IndexedDB hit → validate version and expiry → interface
Validation failure → discard cache → API fallback
Completion evidence
- One business value is not owned by several stores.
- Query keys include user, filter, and page boundaries.
- The interface opens after migration, quota, or storage-access failure.
- Offline state and resynchronization are understandable to the user.
Related terms: Zustand, TanStack Query, IndexedDB
Terms in this content
🎉 You finished From HTML/CSS/JS to React, Next.js, Tailwind
What's next? Pick another course below.