top of page

[Flutter/dart] Determine if rebuilding from the parent widget or by setState ()


Overview


When creating a page with StatefulWidget, I encountered a situation where I want to determine if it was rebuilt from the parent widget or from within the page with setState ().


More specifically, I put the page in the child widget of the Provider so that if a certain state changes, it will be reflected on the page as well.

In the case of rebuilding by Provider, it means that the state has changed, so I would like to perform processing to reflect that.

On the other hand, the change by setState () does not change the monitored state (example: switching pages of BottomNavigation), so I do not want to do this process.


( You may think that I should do it with initState (), but initState only passes the first time when built from Provider etc.)


I would like to describe how to deal with this situation.



Method


  1. Have a bool variable in the StatefulWidget that indicates whether it is a rebuild from the parent widget

  2. When calling the constructor of this StatefulWidget from the parent Widget (Provider, etc.), set this bool variable to true.

  3. Perform the desired processing by referring to the value of this variable in the build() method. Then set this variable to false.

In this way, if you perform the process only once at build time, this process will not pass in the subsequent rebuild by setState ().


A concrete example is shown below.

This page can be switched between 3 pages with Bottom Navigation.

ViewModel is a class that represents a state. Create three pages based on the ViewModel instance.

I would like to perform this page creation process when the contents of the model change, but if I write it in build (), the creation process will run every time the page is switched, which is inefficient.

Therefore, we are taking the above measures.

class basePage extends StatefulWidget{

  ViewModel model;
  bool buildFromParent;

  basePage({this.model, this.buildFromParent});

  @override
  State<StatefulWidget> createState() {
    return basePageState();
  }

}

class basePageState extends State<basePage>{

  List<Widget>_pageList;
  int _pageInd=0;

  @override
  Widget build(BuildContext context) {

    if (widget.buildFromParent) {
      _pageList = [APage(model: widget.model,), 
      BPage(model: widget.model), CPage(model: widget.model,)];
      widget.buildFromParent=false;  //here
    }

    return Scaffold(
      body:  _pageList[_pageInd],
      bottomNavigationBar:BottomNavigationBar(
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.calendar_today)               
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.list),    
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.settings),       
          )
        ],
        currentIndex: _pageInd,
        onTap: (index) {
          setState(() {
            _pageInd = index;
           });
        },
      )
    );
  }

}

The code that calls this basePage is below. Set buildFromParent to true.


@override
Widget build(BuildContext context) {
  return StoreProvider<AppState>(
    store: store,
    child: StoreConnector<AppState, ViewModel>(
      distinct: true,
      converter: (store)=>ViewModel.create(store),
      builder: (BuildContext context, ViewModel model)=>
        basePage(model: model, buildFromParent: true,) //here
    )
  );
}

I often use StoreProvider because I manage the state with redux.



Lastly


Actually, the first measure is to prevent rebuilding as much as possible using const etc., but I think that you may want to change the display content of the page depending on the state.

There is also an opinion that StatelessWidget is enough if you use Provider, but there are cases where you have to use StatefulWidget like BottomNavigation or DropdownButton.

In such a case, please try this method.

Recent Posts

See All

留言


category

Let's do our best with our partner:​ ChatReminder

iphone6.5p2.png

It is an application that achieves goals in a chat format with partners.

google-play-badge.png
Download_on_the_App_Store_Badge_JP_RGB_blk_100317.png

Let's do our best with our partner:​ ChatReminder

納品:iPhone6.5①.png

It is an application that achieves goals in a chat format with partners.

google-play-badge.png
Download_on_the_App_Store_Badge_JP_RGB_blk_100317.png

Theme diary: Decide the theme and record for each genre

It is a diary application that allows you to post and record with themes and sub-themes for each genre.

google-play-badge.png
Download_on_the_App_Store_Badge_JP_RGB_blk_100317.png
bottom of page