StatefulWidget and State: Two Parts of a Whole
A StatefulWidget is an immutable blueprint, while its separate State object holds the mutable data. The widget is disposable; the state persists across rebuilds. Use this for interactive UI like forms or counters.
WHY IT EXISTS Flutter's declarative framework is built on immutable widgets. When a widget's configuration needs to change, Flutter rebuilds it from scratch. This is fast, but it creates a problem: how do you preserve data, like a user's input in a form, across these rebuilds? StatefulWidget solves this by separating the immutable description of the UI from the mutable data that lives within it.
THE MENTAL MODEL Think of a StatefulWidget as a car's design blueprint and its State object as the actual car on the road. The blueprint (the widget) is static and describes how the car should be built. The car itself (the State object) has a current speed, fuel level, and mileage that change over time. You can get a new blueprint to change the car's color, but you're putting that new body on the same underlying engine and chassis (the persistent State object).
HOW IT WORKS When Flutter inflates a StatefulWidget, it calls the widget's createState() method once to create a companion State object. This State object is then permanently associated with that location in the widget tree. The widget itself is immutable and can be rebuilt anytime, but the State object persists. To trigger a UI update, you call the setState() method from within the State object. This function takes a callback where you modify your state variables, then it marks the widget as 'dirty', telling the Flutter engine to re-run the build() method to reflect the changes.
WHEN TO USE IT Use a StatefulWidget for any state that is local to the widget itself, often called 'ephemeral state'. This includes anything that changes dynamically based on user interaction or internal logic. Common examples: first, the current value of a form field or checkbox; second, the progress of an animation; third, the 'is loading' status while fetching data for that specific component.
WHEN NOT TO USE IT For UI that never changes, use a StatelessWidget, as it's more performant. More importantly, avoid using StatefulWidget to manage 'app state'—data that needs to be shared across multiple screens or distant parts of the widget tree. Lifting state that high with StatefulWidgets leads to complex callbacks and rebuilds. For app state, use a dedicated state management solution like Provider, Riverpod, or BLoC.
ONE CANONICAL EXAMPLE A simple counter button. The StatefulWidget, CounterPage, defines the constant parts. Its _CounterPageState object holds a single integer, _counter. The build method displays this integer in a Text widget. A button's onPressed callback calls setState(() { _counter++; }). This single call increments the variable and tells Flutter to rebuild the UI to show the new number, while the State object itself lives on.
Read the original → docs.flutter.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.