Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

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.

What is lifting state up in Flutter?

+1
−0

What does lifting state up in Flutter mean, and how does it work?

History
Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

1 answer

+1
−0

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 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.

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.

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 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 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)

History
Why does this post require moderator attention?
You might want to add some details to your flag.

0 comment threads

Sign up to answer this question »