Skip to content

State Management & Data Flow

Almost every “how do I manage state in React?” argument is really one question: where should this piece of state live? React gives you a ladder of answers, and the skill is climbing only as high as you need.

flowchart TB
  local["Local state
(useState in one component)"] --> lifted["Lifted state
(moved to a common ancestor)"]
  lifted --> context["Context
(shared down a subtree)"]
  context --> store["External store
(Zustand / Redux / Jotai)"]
  note["Climb only as high as you need"] -.-> local
The state-location ladder
LessonWhat you’ll learn
Lifting & compositionLifting state up, prop drilling, and fixing it with composition
ContextuseContext, when it fits, and when it hurts
useReducer patternsReducers, and the context + reducer app-state pattern
External storesWhen to reach for a store, and useSyncExternalStore

Start with the lowest rung that works. Keep state local until two components need it; then lift it to their common parent. Reach for Context only when data is genuinely shared across a whole subtree and changes infrequently (theme, auth, locale). Reach for an external store only when Context’s re-render behavior or the shape of your data makes it painful.

Most state does not need a library. A huge amount of “state management” complexity comes from reaching for the top of the ladder when a useState two components up would have done the job.

What is the core question behind "state management" in React?
What is the recommended approach on the state-location ladder?
When is an external store (Zustand/Redux) actually warranted?