Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Widgets  ›  Lesson

Stateful Widgets

Stateful Widgets 12 minA stateful widget pairs an immutable widget with a long-lived State object, and calling setState inside that object marks it dirty so its build method runs again.

Stateful Widgets

Tapping "Watered" on the fern should tick it off and update the count on screen. That widget must remember something between frames and redraw when it changes. Stateless widgets cannot do that; stateful widgets are built for it.

The rule

Change the value inside setState, and Flutter runs build again.

A stateful widget is two classes:

class WaterCounter extends StatefulWidget {
  const WaterCounter({super.key, required this.plant});
  final String plant;

  @override
  State<WaterCounter> createState() => _WaterCounterState();
}

class _WaterCounterState extends State<WaterCounter> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return TextButton(
      onPressed: () => setState(() => count++),
      child: Text('${widget.plant}: watered $count times'),
    );
  }
}
  • The widget class is immutable, like any widget. It holds the inputs, here plant.
  • The State class is created once by createState and lives as long as the widget stays in the tree. The changing value, count, belongs here.
  • Inside the State, widget.plant reads the widget's inputs.
  • setState runs your change and marks the State as needing a rebuild, so build runs again with the new value.

Two lifecycle methods matter early: initState runs once when the State is created (set up controllers or timers there), and dispose runs when it is removed (clean them up there).

The shortcut

For every piece of data on a screen, trace it: who changes it, and where does it live?

Tracing the water countStep 1 of 4
  1. Who changes it?

    The user, by tapping the button. So it is state, not an input from the parent.

The trap is writing count++; on its own. The number really does change, but nothing asks Flutter to rebuild, so the screen keeps showing the old value until something else happens to trigger a build.

Drills

Answer fast — trust the rule.

quick drill

Where should the changing count be declared?

quick drill

A handler runs count++; without setState. What does the user see?

quick drill

Inside _WaterCounterState, how do you read the plant passed to WaterCounter?

quick drill

Where should you start a timer that must be cancelled later?

Remember

  • Change the value inside setState, and Flutter runs build again.
  • Trace each value: who changes it, and where it lives.
  • Trap: changing a field without setState leaves the screen stale.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainBuild the water counter

Write a stateful widget that shows how many times you have watered a plant today, with a button that adds one. Explain why the count lives in the State class, and what would go wrong if you changed the count without calling setState.