Home > Software engineering >  How to do setstate that depends on multiple futurebuilder
How to do setstate that depends on multiple futurebuilder

Time:08-05

I am making a group buying app, which will show list of nearest deal, newest deal, and ending soon deal. If these 3 lists are empty, I want to show a button for user to add a deal. But I encountered "setState called during Build" error. Here is what I have tried:

int listCount = 0;
bool hasNearest = false;
bool hasNewest = false;
bool hasEnding = false;
bool showButton = false;

void checkState(int count, String mode) {
  listCount = listCount   count;
  if (mode == 'nearest') hasNearest = true;
  if (mode == 'newest') hasNewest = true;
  if (mode == 'ending') hasEnding = true;

  if (hasNearest && hasNewest && hasEnding && listCount <= 0) {
    setState((){
      showButton = true;
    })
  }
}

@override
Widget build(BuildContext context) {
  return Column(
    children: [
      // for nearest deal
      FutureBuilder(
        future: getNearestDealMethod(), // method from other helper class, returning future object
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.done:
              if (snapshot.hasData) {
                List<Deal> list = snapshot.data;
                checkState(list.length, 'nearest');

                if (list.length > 0) { // show deal widget }
              } else {
                return Text("No Deal");
              }
              break;

            default:
              return Text("Error");
          }
        }
      ),
      // for newest deal
      FutureBuilder(
        future: getNewestDealMethod(), // method from other helper class, returning future object
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.done:
              if (snapshot.hasData) {
                List<Deal> list = snapshot.data;
                checkState(list.length, 'newest');

                if (list.length > 0) { // show deal widget }
              } else {
                return Text("No Deal");
              }
              break;

            default:
              return Text("Error");
          }
        }
      ),
      // for ending deal
      FutureBuilder(
        future: getEndingDealMethod(), // method from other helper class, returning future object
        builder: (context, snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.done:
              if (snapshot.hasData) {
                List<Deal> list = snapshot.data;
                checkState(list.length, 'ending');

                if (list.length > 0) { // show deal widget }
              } else {
                return Text("No Deal");
              }
              break;

            default:
              return Text("Error");
          }
        }
      ),
      if (showButton) ...[
        Text('show button here')
      ]
    ]
  );
}

I'm not using a provider to store fetch data, because the client insisted that every time this page is load, app must retrieve the latest value from cloud.

What should I do to make this work? Or is my approach incorrect here? Any help is appreciated.

CodePudding user response:

In a future builder set state will rebuild the ui and call the future again. An option to fix this is to extract the widget to a new class and perform set state in the extracted widget.. or you can consider using some state management libraries like bloc or river pod

CodePudding user response:

Don't pass future function directly just pass the instance of future builder like

Future<List<....>>?futureFile ;

@override void initState() {
 super.initState();
 futureFile = getNearestDealMethod();
 }

 FutureBuilder(
    future: futureFile, // method from other helper class, returning 
 futurobject
    builder: (context, snapshot) {
      switch (snapshot.connectionState) {
     .....
  • Related