Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Post History
This article has a good explanation of lifting state up in Flutter. Let's say for example that we have a BlueSquare widget that displays the number of times it has been tapped. Each click on the...
Answer
#2: Post edited
- [This article](https://medium.com/nerd-for-tech/lifting-state-up-and-callbacks-7a19d0bdbe53) has a good explanation of lifting state up in Flutter.
- >Let's say for example that we have a `BlueSquare` widget that displays the number of times it has been tapped. Each click on the square automatically updates the text displayed with the updated total number of clicks on that square. Let's say then that we wanted to have a set of `BlueSquares` and all the `BlueSquares` in that set display the accumulated number of clicks the user has done.
- This means the number of clicks is a state shared by all the `BlueSquare` objects.
- (Grammar and some minor phrasing corrected in quote above.)
- Instead of making `BlueSquare` a `StatefulWidget`, we make it a `StatelessWidget` and make its parent a `StatefulWidget`. The `StatefulWidget`, `BlueSquareParent`, keeps track of the number of clicks. It passes the number of clicks to the `BlueSquare` widget's constructor so that `BlueSquare` widget can display the current click count.
- ```flutter
- class BlueSquare extends StatelessWidget{
- final int numClicks;
- BlueSquare({
- required this.numClicks
- }) : super();
- Widget build(BuildContext context){
- Container(
- color: Colors.blue,
- height: 30,
- width: 30
- child: TextButton(
- child: const Text("$numClicks")
- )
- );
- }
- }
- class BlueSquareParent extends StatefulWidget {
- BlueSquareParentState createState() => BlueSquareParentState();
- }
- class BlueSquareParentState extends State<BlueSquareParent>{
- //Initialize the number of clicks to 0
- int numClicksTotal = 0;
- @override
- Widget build(){
- return Scaffold(
- body: Column(
- children: [
- BlueSquare(numClicks: numClicksTotal),
- BlueSquare(numClicks: numClicksTotal)
- ]
- )
- );
- }
- }
- ```
- In the `BlueSquare` example, we need to return the number of clicks to the `BlueSquareParent` widget so it knows how many there are. We can do this by passing a callback method to the `BlueSquares` that will let them update the number of clicks in `BlueSquareParent`.
- ```flutter
- class BlueSquare extends StatelessWidget{
- final int numClicks;
- final Function callback;
- BlueSquare({
- required this.numClicks,
- required this.callback
- }) : super();
- Widget build(BuildContext context){
- Container(
- color: Colors.blue,
- onTap: (){
- callback();
- }
- height: 30,
- width: 30
- child: TextButton(
- child: const Text("$numClicks")
- )
- );
- }
- }
- class BlueSquareParent extends StatefulWidget {
- BlueSquareParentState createState() => BlueSquareParentState();
- }
- class BlueSquareParentState extends State<BlueSquareParent>{
- //Initialize the number of clicks to 0
- int numClicksTotal = 0;
- @override
- Widget build(){
- return Scaffold(
- body: Column(
- children: [
- BlueSquare(numClicks: numClicksTotal, callback: addClick),
- BlueSquare(numClicks: numClicksTotal, callback: addClick)
- ]
- )
- );
- }
- void addClick(){
- setState((){
- numClicksTotal++;
- });
- }
- }
- ```
- (All code adapted from the examples in the article.)
- Another example: [This YouTube tutorial](https://www.youtube.com/watch?v=ZqEouycRSzY&list=PLPo5vEiJO3Bigfo2wMYF5xtLjwXJqsPTz&index=7&t=3113s) shows how to lift up state for `TextFormFields` so that the values put into those fields are stored in a parent widget. The child widget (`RangeSelectorTextFormField`) has a `TextFormField` in it and receives a callback method just like the `BlueSquare` widget in the first example. When the text in the field is saved, the callback method is called. In the parent widget, we create a function that sets either the minimum value or the maximum value variable in the parent widget, depending on which text field we're creating, and pass that as the callback method for the `RangeSelectorTextFormField`. Then, when the text in the the `TextFormField` is saved, `RangeSelectorTextFormField` calls the callback method, which sets the associated variable in the parent widget.
[Flutter documentation](https://docs.flutter.dev/development/data-and-backend/state-mgmt/simple) recommends using `Provider` instead of lifting up state this way if you're doing anything much more complicated than the example above.
- [This article](https://medium.com/nerd-for-tech/lifting-state-up-and-callbacks-7a19d0bdbe53) has a good explanation of lifting state up in Flutter.
- >Let's say for example that we have a `BlueSquare` widget that displays the number of times it has been tapped. Each click on the square automatically updates the text displayed with the updated total number of clicks on that square. Let's say then that we wanted to have a set of `BlueSquares` and all the `BlueSquares` in that set display the accumulated number of clicks the user has done.
- This means the number of clicks is a state shared by all the `BlueSquare` objects.
- (Grammar and some minor phrasing corrected in quote above.)
- Instead of making `BlueSquare` a `StatefulWidget`, we make it a `StatelessWidget` and make its parent a `StatefulWidget`. The `StatefulWidget`, `BlueSquareParent`, keeps track of the number of clicks. It passes the number of clicks to the `BlueSquare` widget's constructor so that `BlueSquare` widget can display the current click count.
- ```flutter
- class BlueSquare extends StatelessWidget{
- final int numClicks;
- BlueSquare({
- required this.numClicks
- }) : super();
- Widget build(BuildContext context){
- Container(
- color: Colors.blue,
- height: 30,
- width: 30
- child: TextButton(
- child: const Text("$numClicks")
- )
- );
- }
- }
- class BlueSquareParent extends StatefulWidget {
- BlueSquareParentState createState() => BlueSquareParentState();
- }
- class BlueSquareParentState extends State<BlueSquareParent>{
- //Initialize the number of clicks to 0
- int numClicksTotal = 0;
- @override
- Widget build(){
- return Scaffold(
- body: Column(
- children: [
- BlueSquare(numClicks: numClicksTotal),
- BlueSquare(numClicks: numClicksTotal)
- ]
- )
- );
- }
- }
- ```
- In the `BlueSquare` example, we need to return the number of clicks to the `BlueSquareParent` widget so it knows how many there are. We can do this by passing a callback method to the `BlueSquares` that will let them update the number of clicks in `BlueSquareParent`.
- ```flutter
- class BlueSquare extends StatelessWidget{
- final int numClicks;
- final Function callback;
- BlueSquare({
- required this.numClicks,
- required this.callback
- }) : super();
- Widget build(BuildContext context){
- Container(
- color: Colors.blue,
- onTap: (){
- callback();
- }
- height: 30,
- width: 30
- child: TextButton(
- child: const Text("$numClicks")
- )
- );
- }
- }
- class BlueSquareParent extends StatefulWidget {
- BlueSquareParentState createState() => BlueSquareParentState();
- }
- class BlueSquareParentState extends State<BlueSquareParent>{
- //Initialize the number of clicks to 0
- int numClicksTotal = 0;
- @override
- Widget build(){
- return Scaffold(
- body: Column(
- children: [
- BlueSquare(numClicks: numClicksTotal, callback: addClick),
- BlueSquare(numClicks: numClicksTotal, callback: addClick)
- ]
- )
- );
- }
- void addClick(){
- setState((){
- numClicksTotal++;
- });
- }
- }
- ```
- (All code adapted from the examples in the article.)
- Another example: [This YouTube tutorial](https://www.youtube.com/watch?v=ZqEouycRSzY&list=PLPo5vEiJO3Bigfo2wMYF5xtLjwXJqsPTz&index=7&t=3113s) shows how to lift up state for `TextFormFields` so that the values put into those fields are stored in a parent widget. The child widget (`RangeSelectorTextFormField`) has a `TextFormField` in it and receives a callback method just like the `BlueSquare` widget in the first example. When the text in the field is saved, the callback method is called. In the parent widget, we create a function that sets either the minimum value or the maximum value variable in the parent widget, depending on which text field we're creating, and pass that as the callback method for the `RangeSelectorTextFormField`. Then, when the text in the the `TextFormField` is saved, `RangeSelectorTextFormField` calls the callback method, which sets the associated variable in the parent widget.
- [Flutter documentation](https://docs.flutter.dev/development/data-and-backend/state-mgmt/simple) recommends using `Provider` instead of lifting up state this way if you're doing anything much more complicated than the example above.
- (Original post on StackOverflow [here](https://stackoverflow.com/questions/74058512/simple-explanation-of-lifting-state-up/74058928#74058928))
#1: Initial revision
[This article](https://medium.com/nerd-for-tech/lifting-state-up-and-callbacks-7a19d0bdbe53) has a good explanation of lifting state up in Flutter. >Let's say for example that we have a `BlueSquare` widget that displays the number of times it has been tapped. Each click on the square automatically updates the text displayed with the updated total number of clicks on that square. Let's say then that we wanted to have a set of `BlueSquares` and all the `BlueSquares` in that set display the accumulated number of clicks the user has done. This means the number of clicks is a state shared by all the `BlueSquare` objects. (Grammar and some minor phrasing corrected in quote above.) Instead of making `BlueSquare` a `StatefulWidget`, we make it a `StatelessWidget` and make its parent a `StatefulWidget`. The `StatefulWidget`, `BlueSquareParent`, keeps track of the number of clicks. It passes the number of clicks to the `BlueSquare` widget's constructor so that `BlueSquare` widget can display the current click count. ```flutter class BlueSquare extends StatelessWidget{ final int numClicks; BlueSquare({ required this.numClicks }) : super(); Widget build(BuildContext context){ Container( color: Colors.blue, height: 30, width: 30 child: TextButton( child: const Text("$numClicks") ) ); } } class BlueSquareParent extends StatefulWidget { BlueSquareParentState createState() => BlueSquareParentState(); } class BlueSquareParentState extends State<BlueSquareParent>{ //Initialize the number of clicks to 0 int numClicksTotal = 0; @override Widget build(){ return Scaffold( body: Column( children: [ BlueSquare(numClicks: numClicksTotal), BlueSquare(numClicks: numClicksTotal) ] ) ); } } ``` In the `BlueSquare` example, we need to return the number of clicks to the `BlueSquareParent` widget so it knows how many there are. We can do this by passing a callback method to the `BlueSquares` that will let them update the number of clicks in `BlueSquareParent`. ```flutter class BlueSquare extends StatelessWidget{ final int numClicks; final Function callback; BlueSquare({ required this.numClicks, required this.callback }) : super(); Widget build(BuildContext context){ Container( color: Colors.blue, onTap: (){ callback(); } height: 30, width: 30 child: TextButton( child: const Text("$numClicks") ) ); } } class BlueSquareParent extends StatefulWidget { BlueSquareParentState createState() => BlueSquareParentState(); } class BlueSquareParentState extends State<BlueSquareParent>{ //Initialize the number of clicks to 0 int numClicksTotal = 0; @override Widget build(){ return Scaffold( body: Column( children: [ BlueSquare(numClicks: numClicksTotal, callback: addClick), BlueSquare(numClicks: numClicksTotal, callback: addClick) ] ) ); } void addClick(){ setState((){ numClicksTotal++; }); } } ``` (All code adapted from the examples in the article.) Another example: [This YouTube tutorial](https://www.youtube.com/watch?v=ZqEouycRSzY&list=PLPo5vEiJO3Bigfo2wMYF5xtLjwXJqsPTz&index=7&t=3113s) shows how to lift up state for `TextFormFields` so that the values put into those fields are stored in a parent widget. The child widget (`RangeSelectorTextFormField`) has a `TextFormField` in it and receives a callback method just like the `BlueSquare` widget in the first example. When the text in the field is saved, the callback method is called. In the parent widget, we create a function that sets either the minimum value or the maximum value variable in the parent widget, depending on which text field we're creating, and pass that as the callback method for the `RangeSelectorTextFormField`. Then, when the text in the the `TextFormField` is saved, `RangeSelectorTextFormField` calls the callback method, which sets the associated variable in the parent widget. [Flutter documentation](https://docs.flutter.dev/development/data-and-backend/state-mgmt/simple) recommends using `Provider` instead of lifting up state this way if you're doing anything much more complicated than the example above.