Skip to main content

Step 12

Step 12 — Separate server state, UI state, and local data

2 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.