Ah-hoc stateful widgets using StatefullBuilder
Flutter and its declarative paradigm is quite great. The declarative way of building UIs means you only need to "bind" properties to elements.
As long as you update your property's value inside setState()
of a StatefulWidget
, the value will magically be reflected in the UI.
But what happens when you have a Widget
that accepts a builder
and you need to have something that has a state? Sure, you can just create a new StatefulWidget
and return that from the builder
. But this might be too verbose if you want to build something small.
This is where StatefulBuilder
comes into play. It's a widget that provides a StateSetter
to be able to call the familiar setState()
when building a widget "ad-hoc" (e.g. from a builder
).
Let me give you an example and explain it line by line. The showModalBottomSheet
is a convenient method for showing a dialog popping up from the bottom of the screen. This method has a builder
parameter to build the widget for the content of this dialog.
void openModal(
BuildContext context, MyViewModel viewModel) => // 1.
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) => StatefulBuilder( // 2.
builder: (BuildContext context, StateSetter setState) => // 3.
TextButton(
child: Text(viewModel.counter.toString()),
onPressed: () => setState(() => viewModel.counter++)))); // 4.
- The approach of using a
StatefulBuilder
described here has the caveat that the state should be stored outside of thebuilder
(e.g. in a ViewModel) since the builder will be called every time thesetState()
is called. - The
showModalBottomSheet()
method has abuilder
parameter for the content of the modal. Here is where we return ourStatefullBuilder
. - The
StatefulBuilder
'sbuilder
provides theStateSetter
we will use it later when we want to update the contents of the modal. - In the
onPressed
we don't just update our data. Instead, we update our data inside the familiarsetState()
. TheStatefulBuilder
'sbuilder
will be called again and the content of the modal will be updated.
Hopefully, by now it's clear how to return stateful widgets in builder
s without creating new StatefulWidget
s, but by using the StatefullBuilder
.
Happy coding!