FutureBuilder, SetState: Variable Not Updating When Deleting setState

Issue

I learned that it’s not good practice to have a setState(() AND a FutureBuilder together. When I delete my setState((), I noticed that the isWaiting variable no longer updates into the MakeCards class and stays at True. But when I leave in my setState, even if it’s empty setState((){ } then isWaiting properly updates to False as it should. I need help with understanding why that is and how I can update isWaiting to False inside the MakeCards while deleting my setState(().

    bool isWaiting = true; <------------------------------------------
        
            Future<Map> getData() async {
                try {
                  List<String> coinData = await CoinData();
                  Map<String, List<String>> graphData = await GraphData()
                  
                  setState(() { <------------------------------------
                    coinValues = coinData;
                    graphValues = graphData;
                  });

                   isWaiting = false; <----------------------------------
            .
            . (some code)
            .
                return allDataValues;
              }
    

Build Method

                 MakeCards(
                    isWaiting: isWaiting, <-----------------------------
                    selectedCurrency: selectedCurrency,
                    coinData: allDataValues['lastCoinPrices'])
                .makeCards(),
    
                 FutureBuilder<Map>(
                      future: futureData,
                      builder: (context, snapshot) {
                        print("FutureBuilder started");
                        if (!snapshot.hasData)
                          return CircularProgressIndicator();
                        else if (snapshot.data.isEmpty)
                          return Container();
                        else {
                          print("FutureBuilder completed");
                          return Graph(snapshot.data);
                        }
                      })

MakeCards (separate file)

class MakeCards {
  MakeCards({this.isWaiting, this.selectedCurrency, this.coinData});

  bool isWaiting;
  String selectedCurrency;
  List<String> coinData = [];

  Row makeCards() {
    List<CryptoCard> cryptoCards = [];
    for (int i = 0; i < cryptoAbbreviation.length; i++) {
      cryptoCards.add(
        CryptoCard(
          cryptoCurrency: cryptoAbbreviation[i],
          selectedCurrency: selectedCurrency,
          value: isWaiting ? '---' : coinData[i], <-------------------------
          name: cryptoName[i],
          // iconContent: iconContent,
        ),
      );
    }

    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: cryptoCards,
    );
  }
}

Solution

You don’t need setState while you are using FutureBuilder.

You may move the Future builder to the root of your widget tree (the part of the tree that depends on the data from that future)

Then replace the value passed through the variable isWaiting with the state of the snapshot.

Answered By – MSaudi

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *