Theo
Theo

Reputation: 110

Using Flutter Riverpod's StreamProvider to fetch a specific document from Firestore

I am using Riverpod's StreamProvider to fetch a field from Firestore containing an array then mapping it to a class as follows.

final firebaseFollowingProvider = StreamProvider<List<Following>>((ref) {
  final stream = FirebaseFirestore.instance.collection('following').doc('d48391af-380d-4377-a3f9-d38cf5af7923').snapshots();
  return stream.map((snapshot) => snapshot.data()!.map((doc) => Following.fromDocument(doc)).toList());
});

My Model looks like this

class Following {
  dynamic following;

  Following({this.following});

  Following.fromJson(Map<String, dynamic> json)
      : following = json['isFollowing'];

  Map<String, dynamic> toJson() => {
        'isFollowing': following,
      };

  factory Following.fromDocument(DocumentSnapshot doc) {
    return Following(following: doc['isFollowing']);
  }
}

The error I am getting is

The argument type 'MapEntry<_, > Function(String)' can't be assigned to the parameter type 'MapEntry<dynamic, dynamic> Function(String, dynamic)'. (Documentation) The return type 'Following' isn't a 'MapEntry<, _>', as required by the closure's context. (Documentation)

Since snapshot.data() already returns a Map, how can I map the data returned from the StreamProvider to a class?

I am using cloud_firestore: ^2.3.0

Thank you very much.

Structure of the Database

Upvotes: 1

Views: 1342

Answers (2)

Theo
Theo

Reputation: 110

The issue was I was returning a List of type Following, i.e <List<Following>> instead of returning Following

final firebaseFollowingProvider = StreamProvider.autoDispose<Following>((ref) {
  final stream = followingRef.doc('d48391af-380d-4377-a3f9-d38cf5af7923').snapshots();
  return stream.map((snapshot) => Following.fromDocument(snapshot));
});

Upvotes: 2

bizz84
bizz84

Reputation: 2272

Don't define variables as dynamic inside your model class. Model classes are meant to give you type safety, and dynamic variables escape the type system.

This would be better (haven't tested it):

class Following {
  final String following;

  Following({required this.following});

  Following.fromJson(Map<String, dynamic> json)
      : following = json['isFollowing'] as String;

  Map<String, dynamic> toJson() => {
        'isFollowing': following,
      };

  factory Following.fromDocument(DocumentSnapshot doc) {
    return Following(following: doc['isFollowing'] as String);
  }
}

Upvotes: 0

Related Questions