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.
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
StatefulBuilderdescribed here has the caveat that the state should be stored outside of the
builder(e.g. in a ViewModel) since the builder will be called every time the
showModalBottomSheet()method has a
builderparameter for the content of the modal. Here is where we return our
StateSetterwe will use it later when we want to update the contents of the modal.
- In the
onPressedwe don't just update our data. Instead, we update our data inside the familiar
builderwill be called again and the content of the modal will be updated.
Hopefully, by now it's clear how to return stateful widgets in
builders without creating new
StatefulWidgets, but by using the