State Management
State management is one question
Section titled “State management is one question”There are a dozen state management packages and a hundred blog wars, but they all answer the same two-part question:
Where does this piece of state live, and which widgets rebuild when it changes?
Everything else — setState, InheritedWidget, Provider, Riverpod, BLoC — is a different mechanism for answering it. Once you see them that way, choosing between them stops being tribal and becomes a matter of scope.
Two kinds of state
Section titled “Two kinds of state”The most useful split is not “which package” but how far the state reaches:
flowchart TB eph["Ephemeral state (one widget: a checkbox, a text field, an animation)"] --> local["setState lives in one State object"] app["App state (shared: auth, cart, settings, cached data)"] --> shared["InheritedWidget / Provider / Riverpod / BLoC"]
- Ephemeral (local) state belongs to a single widget and nobody else cares — the current page of a
PageView, whether a checkbox is ticked, an animation value.setStateis the correct, complete answer. Reaching for a global store here is over-engineering. - App (shared) state is needed by many widgets across the tree — the logged-in user, a shopping cart, a theme, data fetched from an API. This is where the dedicated approaches earn their keep.
Most real bugs and most over-engineering come from putting state in the wrong category.
What this module covers
Section titled “What this module covers”| Lesson | What you’ll learn |
|---|---|
| setState & lifecycle | How rebuilds actually happen, and the State lifecycle |
| InheritedWidget | The primitive that makes propagating state down the tree efficient |
| Provider & Riverpod | The ergonomic, widely used shared-state approaches |
| BLoC & patterns | Unidirectional data flow for complex apps |
| Choosing an approach | A decision guide and how to layer your app |