Cohchi
Cohchi

Reputation: 563

Get collection from firestore, .map doesn't work (flutter)

I'm using Flutter with firebase for my app.

I started my application by putting all my code in the main. dart I now want to organize my files well but I am facing a problem.

I created a service folder, with a database. dart file in which I made a class to find my items in firestorm

the problem is that I do not pass in the snapshot. docs.map ((doc))

here is my code in database. dart

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutterfirebase/models/todo_model.dart';

class DatabaseService {
  DatabaseService();

  final CollectionReference itemsCollection =
      FirebaseFirestore.instance.collection("items");

  Stream<List<TodoItem>> get todos {
    return itemsCollection.snapshots().map((QuerySnapshot snapshot) {
      inspect(snapshot.docs);
      return snapshot.docs.map((DocumentSnapshot doc) {
        print('here');
        inspect(doc);
        return TodoItem(text: doc.data()['text'], done: doc.data()['done']);
      });
    });
  }
}

the print(snapshot.docs.length); returns 4. The inspect(snapshot.docs) works, I can see my 4 queryDocumentSnapshot with my id

but the print('here') does not appear, nor the inspect(doc)

can you help me figure out what's going on, please?

here are the versions of the packages

firebase_core: ^1.0.2

cloud_firestore: ^1.0.3

Thanks

Upvotes: 0

Views: 268

Answers (2)

Ramiro
Ramiro

Reputation: 36

The print('here') does not appear because the transformation function provided to .map is not executed immediately. map returns an Iterable and, according to the official docs:

The returned iterable is lazy, so it won't iterate the elements of this iterable until it is itself iterated, and then it will apply toElement to create one element at a time

In other words, since you do not iterate over the result of your map, the function inside map is never called. One way to force the iteration is to convert the result of map to a List using toList() method.

In Dartpad, you can test this by running the following example:

  final List<int> numbers = [1, 2, 3];
  final iterable = numbers.map((num) {
    print('inside map, num is: $num');
    return num + 1;
  }).toList();

If you try and remove the toList() from the result of the map above the print is never executed.

To address the original example, please try adding toList as follows:

 snapshot.docs.map((DocumentSnapshot doc) {
        print('here');
        inspect(doc);
        return TodoItem(text: doc.data()['text'], done: doc.data()['done']);
      }).toList();

Upvotes: 0

Osama Abdelaziz
Osama Abdelaziz

Reputation: 140

I think you should return QuerySnapshot from the stream not DocumentSnapshot, just like this

Stream<List<TodoItem>> getSomeoneItems() {
  return FirebaseFirestore.instance.collection('items')
    .snapshots()
    .map((qSnap) =>
        qSnap.docs.map((doc) => TodoItem.fromJson(doc.data())).toList());
}

then you can use this stream in your view inside StreamBuilder widget.

Upvotes: 3

Related Questions