Lesson 6 of 30
Before picking a state library, a strong system design answer classifies the state itself — local, shared, or server-owned each have genuinely different needs, and conflating them is where most real designs go wrong.
13 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
A dashboard fetches a list of orders from an API and also lets the user pick a sort column client-side. Which category does the fetched order list itself belong to?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
Every piece of state in a frontend app falls into one of three categories, and the category should drive where and how it's stored — not habit, not whatever's already in the codebase.
useState's home turf; reaching for a global store here is pure overhead.Naming that third category explicitly, out loud, is one of the highest-signal moves in a system design interview — it's the distinction that separates "I'll put everything in Redux" from an answer that actually reflects how modern apps are built.
Say the prompt is "design the state for a dashboard listing a company's orders, with client-side filters and sorting." A shallow answer reaches for one big store holding everything. A stronger answer separates it: the fetched order list is server state — it needs a fetch, a loading state, and a way to know if it's stale after a mutation elsewhere in the app. The currently selected filter and sort column are shared client state — no server round-trip needed, but shared between the filter bar and the table. Whether a single row's detail panel is expanded is local UI state, scoped to that row.
Once server and client state are pulled apart, the shape of the client state itself becomes its own decision: nested (denormalized) versus normalized. A nested shape mirrors the API response directly — an array of order objects, each with its full customer object embedded — and is the simplest thing to reach for first. It breaks down the moment the same entity appears in more than one place: update a customer's name in the order list and in a currently-open detail view, and now there are two independent copies that can drift out of sync unless every update site remembers to touch both. A normalized shape stores each entity once, keyed by id, with everything else referencing it by that id — updating the customer once updates every place that renders it. The cost is real: normalizing takes upfront structuring work and makes reads slightly less direct (a lookup instead of an inline value), which is exactly why it's a tradeoff worth naming rather than a default to reach for everywhere.
"How would you structure the state for this feature?" is one of the most frequently asked frontend system design questions, and the strongest signal a candidate can give is correctly sorting a prompt's state into local/shared/server categories before naming a single tool.