State Management & Data Flow
The one question
Section titled “The one question”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
What this module covers
Section titled “What this module covers”| Lesson | What you’ll learn |
|---|---|
| Lifting & composition | Lifting state up, prop drilling, and fixing it with composition |
| Context | useContext, when it fits, and when it hurts |
| useReducer patterns | Reducers, and the context + reducer app-state pattern |
| External stores | When to reach for a store, and useSyncExternalStore |
The guiding principle
Section titled “The guiding principle”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.