Joe
Joe

Reputation: 1039

Firebase list is not updating in set state

The Flutter setState function not updating the list after retrieving from Firebase.

I am trying to develop a Flutter app. I am not getting updating the list in setState() function. The list is successfully retrieving from firebase. I have written the firebase connections in Services.dart file.

But my method _getList() is not getting the value in main.dart file.

main.dart

    class DetailsPageState extends State<DetailsPage> {

    List<Product> list;

        @override
    void initState() {
        _checkUser();  // for getting user id from firebase auth
    }

        @override
    Widget build(BuildContext context) {
            return new Scaffold(
                body: new Container(
                    child:new Text("data");
                );
            )
    }

    void _checkUser(){
        debugPrint("Entering in _checkUser");
        this.firebaseAuth.onAuthStateChanged.listen((firebaseUser)async{
            _getList(firebaseUser.uid);
        });
    }


    void _getList(String id)
    debugPrint("Entering in _getList");
        Services.retrieveItems(firestore, uid).then((onValue){
                setState(() {
                    list=onValue;
                        debugPrint("items list:"+onValue.length.toString());
                        debugPrint("items list:"+listCart.length.toString());
                });
        });
        }
    }

Services.dart

    static Future<List> retrieveItems(Firestore firestore, String userId) async {
        List<Product> items = new List<Product>();
        try {
        firestore.collection("Items").document(userId)
        .collection("ItemsMain").snapshots().listen((QuerySnapshot snapshot)  {
            List docList = snapshot.documents;
            items = snapshot.documents.map((documentSnapshot) => Product.fromMap(documentSnapshot.data)).toList();
            debugPrint("items:"+items.length.toString());
            //return items;
        });
        } on Exception catch (e) {
        print (e.toString());
        }

        debugPrint("items 2:"+items.length.toString());
        return items;
    }

Expected results:

Entering in _checkUser

Entering in _getList

items:6

items 2:6

items list:6

items list:6

Actual results:

Entering in _checkUser

Entering in _getList

items list:0

items list:0

items 2:0

items:6

Upvotes: 2

Views: 1954

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 598901

You're returning the items before they are loaded. The simplest way to fix this is to use await in retrieveItems to wait for the data to be loaded from Firestore:

static Future<List> retrieveItems(Firestore firestore, String userId) async {
    List<Product> items = new List<Product>();
    var snapshot = await firestore.collection("Items").document(userId)
                                  .collection("ItemsMain").getDocuments()
    List docList = snapshot.documents;
    items = snapshot.documents.map((documentSnapshot) => Product.fromMap(documentSnapshot.data)).toList();
    debugPrint("items:"+items.length.toString());

    return items;
}

You'll note that I:

  • Call get() instead of listen(). Since listen() starts actively monitoring the collection, it is impossible to say when it is "done". A get() on the other hand, returns the documents once, and is then done.
  • Removed the exception handling, just to make the code a bit more readable. But I also recommend only adding exception handlers in functional code like this if you're actually handling the exception. Leave "log and continue" handlers for higher-level code, such as your main method.

Upvotes: 2

Related Questions