The wrong question is 'which state library?'
State belongs where its source of truth and lifetime make sense. A modal's open state is different from a product filter, which is different again from a saved cart. Treating them all as global state creates coupling; treating them all as local state makes shared behavior drift apart.
- Local UI state: a tooltip, uncontrolled input draft, or one component's animation.
- Lifted state: a value two sibling components must coordinate around.
- URL state: shareable, bookmarkable filters, tabs, pagination, and search queries.
- Server state: data fetched from an API and subject to becoming stale.
- Global client state: authenticated client-only preferences or cross-app workflow state.
Walk through a product search page
The text currently being typed can stay local for fast feedback. The submitted search term, page, sort, and selected filters belong in the URL so a colleague can share the exact view. Search results belong in a server-data cache because the server owns them. A temporary comparison drawer may be global if it persists across routes.
This gives each value one owner. The result is fewer synchronization effects and fewer cases where one view updates but another does not.
Duplicated state is a quiet source of bugs
Storing both selectedProduct and selectedProductId invites disagreement. So does copying a prop into state 'for convenience'. Prefer storing the smallest source value and deriving everything else in render. Derived values should usually be ordinary variables, not effect-driven state.
// Avoid two sources of truth
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const fullName = `${firstName} ${lastName}`;The ownership test
Before creating state, ask four questions: who can change it, who must read it, should a refreshed page retain it, and is the server authoritative? Your answer normally points to its home. Add a global store only after the answers clearly cross route and component boundaries.
Key Takeaways
- State location follows ownership, audience, persistence, and authority.
- URL state is product state when users should share or restore it.
- Derive values during render instead of maintaining duplicate state.
Ready to explain this under interview pressure?
Learn the mental models, then practise applying them to realistic frontend problems.
Join Cohort 3 Waitlist