William Chidube
William Chidube

Reputation: 193

Get value from one future and use it in another future, with Flutter

I have a favourites collection saved under a users collection. Each of the favourite documents has one field which contains a product_Id. I want to retrieve this product_id value and use it to query another collection. This second collection holds the actual products documents.

Retrieving all the documents in the favourite collection. What do I do next to get the value of the product_id fields as strings?

  getIdsfromUserFavs(userId) async {
    var _favData = await _usersCollectionReference
        .doc(userId)
        .collection('favourites')
        .get();


  }

This is the second method that is used to query the products collection. This method needs the String value from above in order to successfully make the query.

  Future<QuerySnapshot<Object?>> queryFavsCollection(value) async {
    var _favedProducts = await _productsCollectionReference
        .where('prod_id', isEqualTo: value)
        .get();
    print(value);
    return _favedProducts;
  }

I am using a futureBuilder in the UI.

THis is one way I have tried(The problem with this is that I don't get any data returned):

  getIdsfromUserFavs(userId) async {
    var _favData = await _usersCollectionReference
        .doc(userId)
        .collection('favourites')
        .get();

    var allData = _favData.docs.map((doc) => doc.data()).toList();
    allData.forEach((element) async {
      String value = element['prod_id'];
      print(value);
      await queryFavsCollection(value);
    });
  }


  Future<QuerySnapshot<Object?>> queryFavsCollection(value) async {
    var _favedProducts = await _productsCollectionReference
        .where('prod_id', isEqualTo: value)
        .get();
    print(value);
    return _favedProducts;
  }

I can see that the above methods print the ids to the console. But the FutureBuilder doesn't receive any data:

I/flutter ( 4628): 3nHHEWuCDXvbhYfT8ljY
I/flutter ( 4628): MptYFV1oXhflDYkdQyIP
I/flutter ( 4628): Fd2ntXyNVmjn0D6mG3RA

Upvotes: 0

Views: 1259

Answers (1)

Hemal Moradiya
Hemal Moradiya

Reputation: 2097

Below function will return all data from favourite collection

  Future<QuerySnapshot<Map<String, dynamic>>> getIdsfromUserFavs(userId) async {
    QuerySnapshot<Map<String, dynamic>> _favData = await _usersCollectionReference
    .doc(userId)
    .collection('favourites')
    .get();

    return _favData; // This will return all data of favourite collection
  }

After that you can return List of desire data as shown in below function

  Future<List<QueryDocumentSnapshot<Map<String, dynamic>>>> queryFavsCollection(userId) async {
   // Will store data in this list so at the end we can return this
    List<QueryDocumentSnapshot<Map<String, dynamic>>> favData = [];     
    QuerySnapshot<Map<String, dynamic>> _favData =
        await getIdsfromUserFavs(userId);
    for (QueryDocumentSnapshot<Map<String, dynamic>> data in _favData.docs) {
      String value = data['prod_id'];
      QuerySnapshot<Map<String, dynamic>> _fav = await 
          _productsCollectionReference
          .where('prod_id', isEqualTo: value)
          .get();

      if (_fav.docs.isNotEmpty) {
        _fav.docs.forEach((element) {
          favData.add(element);
        });
      }
    }

    return favData;
  }

Now you can use FutureBuilder as shown below

FutureBuilder<List<QueryDocumentSnapshot<Map<String, dynamic>>>>(
      future: queryFavsCollection(userId),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return Text('Loading...');
        }
        return Text('you data');
      },
    );

For better practice kindly refer this. This is from flutter documentation

"The future must have been obtained earlier, e.g. during State.initState, State.didUpdateWidget, or State.didChangeDependencies. It must not be created during the State.build or StatelessWidget.build method call when constructing the FutureBuilder. If the future is created at the same time as the FutureBuilder, then every time the FutureBuilder's parent is rebuilt, the asynchronous task will be restarted."

Upvotes: 1

Related Questions