Foundations
Mental models of state.
- Ⅰ. Server vs client state
- Ⅱ. One source of truth
- Ⅲ. Server data is NOT state
UI state is one of those things that feels simple until it isn't.
You start with useState here and useEffect there. The app grows. A new engineer joins and adds a global store. Someone else caches an API response in Redux because it was convenient. Six months later, you have three sources of truth, and nobody can tell you with confidence what the UI is actually showing.
Most of these problems share the same root cause: we treat all data the same way, even when it isn't.
Ⅰ. Server state is not client state
You observe server state. You don't own it. Stop copying it into state management libraries.
As you interact with the app, data moves through this lifecycle. The client holds it temporarily. The server is where it ultimately lives.
This leads to a simple but important conclusion:
- Server state = long-term persistent storage (the source of truth)
- Client state = short-term in-memory storage (temporary updates)
The client state contains the updates that eventually need to be persisted. The server is the authority.
Ⅱ. One source of truth
The most common mistake people make is creating multiple sources of truth. This can often happen by trying to use a state management library to store API/HTTP responses.
When you do that, you're trying to keep the store in sync with what the API says. Now you have a mess. The store has one version. The database has another. Keeping them in agreement becomes your team's problem.
The smarter approach
Server and API state belong in a tool designed for API caching, such as TanStack Query. Keep your UI state in useState or hooks.
Ⅲ. Server data is NOT state
Although server state can serve as the starting point for client state (as in edit flows), client state ultimately tracks user inputs and interactions.
Think of it this way: client state tracks what happens to data between two points in time:
- Default data from the server. For example, loading an edit form
- The update request. The HTTP call that saves changes
Between those two points, the client owns the data. Once the server confirms, the client lets go.
The Sacred 4 UI Flows
Managing inputs. Form state, validation, and the event-handling patterns that don't collapse under their own weight.
Additional modules under development
Managing inputs
Form state, validation, and event handling patterns that actually scale.
Displaying outputs
React Query integration, server caching strategies, and data fetching patterns.
Wizard case study
A complete wizard tying everything together with URL state, multi-step forms, and database integration.