intermediate
Server state vs client state
Separate remote cached data from UI-only interaction state, form drafts, selections, and ephemeral flags.
Server state is remote, asynchronous, shared, and eventually consistent: lists, details, permissions from APIs. Client state is UI-owned and synchronous: selected tab, modal open, form draft before submit, optimistic overlay.
| Dimension | Server state | Client state | |-----------|--------------|--------------| | Source of truth | Backend | Browser UI | | Staleness | Expected | N/A | | Tooling | TanStack Query, SWR, RTK Query | useState, Zustand, Redux | | Invalidation | Keys, tags, refetch | Local setState |
Do not mirror entire API responses into Redux if a cache library already handles freshness, deduplication, and background refetch. Keep client state for what the server does not know yet.
The trade-off is fewer libraries versus mental overhead: two categories of state mean two invalidation models, but mixing them in one store hides bugs.
On interviews: explain why a product list belongs in a query cache while "sort column clicked" stays local.
Common pitfalls: Redux as a manual fetch cache, duplicating server data in two places, and treating loading/error as permanent store shape instead of request metadata.
Checklist:
- Server truth stays on the server.
- Cache libraries own remote freshness.
- Client store for UI-only coordination.
- Sync writes back through mutations + invalidation.