Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flutter setstate rebuild only one child

in flutter I need that when I call setstate, it only rebuilds a widget

I put 2 children in a stack, I need that when a button is pressed, only the second one is rebuilt.

bool popup = false;

Scaffold(
  appBar: AppBar(
    title: const Text('TEST'),
    actions: <Widget>[
      IconButton(                       // + BUTTON
        icon: Icon(Icons.add),
        onPressed: () {
          setState(() {
            popup = true;
          });
        },
      ),
      IconButton(                       // - BUTTON
        icon: Icon(Icons.remove),
        onPressed: () {
          setState(() {
            popup = false;
          });
      ),
    ],
  ),
  body: SafeArea(
    child: Stack(
      children: <Widget>[

        Container(                                        // FIRST WIDGET
          key: ValueKey(1),
          child: Text("Random - "+new Random().nextInt(20).toString())
        ),

        popup ? Center(child: Text("abc")) : Text("") ,   // SECOND WIDGET

      ],

    ),
  ),
);

I expect that when I press the "+" button only the second widget will be re-built, but now it will rebuild all the contents of the stack.

thank you all.

like image 325
John Avatar asked Oct 28 '25 17:10

John


1 Answers

From the official docs we can read:

"When setState() is called on a State, all descendent widgets rebuild. Therefore, localize the setState() call to the part of the subtree whose UI actually needs to change. Avoid calling setState() high up in the tree if the change is contained to a small part of the tree."

My suggestion, and I use it most of the times, is separate the widget that you want to rebuild in a new StatefulWidget. This way the setState only will be rebuild that widget.

    class MyAppBar extends StatefulWidget
    ...
    class _MyAppBarState extends State<MyAppBar> {
    bool popup = false;

     @override
      Widget build(BuildContext context) {
        return AppBar(
           title: const Text('TEST'),
           actions: <Widget>[
           IconButton(                       // + BUTTON
             icon: Icon(Icons.add),
             onPressed: () {
               setState(() {
               popup = true;
             });
            },
           ),
          IconButton(                       // - BUTTON
            icon: Icon(Icons.remove),
            onPressed: () {
              setState(() {
              popup = false;
            });
          ),
        ],
       ), 
      }

Then call it in your Scaffold:

Scaffold(
  appBar: MyAppBar(), 

Other method I can suggest is using ValueNotifier or notifyListeners(). Please read this page Avoid rebuilding all the widgets repetitively. It is well explained.

like image 105
Richardd Avatar answered Oct 31 '25 11:10

Richardd