For some reason, Future.wait() is constantly returning null. I'm not completely certain I am using it correctly.
For context, I have a collection of posts in Firebase. For each post, I can extract the userID assigned to it, then for each post individually I use the userID of the poster to grab the username for display purposes. I grab the Post from a snapshot:
static Future<Post> fromSnapshot(QueryDocumentSnapshot<Object?> doc) async {
final _documentId = doc.id;
final _title = doc.get('title');
final _text = doc.get('text');
final _createdOn = doc.get('createdOn');
final _userID = doc.get('userID');
final userDoc = await FirebaseFirestore.instance.collection('users').doc(_userID).get();
final username = userDoc.get("username");
return Post(documentId: _documentId, title: _title, text: _text, createdOn: _createdOn, username: username);
}
and the extraction of posts occurs in a getPosts() function elsewhere:
Future<List<Post>> getPosts() async {
QuerySnapshot posts = await FirebaseFirestore.instance.collection('posts').get();
final allData = posts.docs.map(
(doc) async => await Post.fromSnapshot(doc)
).toList();
print(allData); // [Instance of 'Future<Post>', Instance of 'Future<Post>', Instance of 'Future<Post>']
final futurePosts = Future.wait(allData);
print(futurePosts); // Instance of 'Future<List<Post>>'
// why does this always return null?
return futurePosts;
}
the problem is it has to be async to extract the posts but also to get the username, meaning it returns a future list of future posts. I want to pass the result of getPosts() to a FutureBuilder, so I need a Future List of posts, and to not make all the posts Future I use Future.wait - but that always seems to return null. Essentially, I am mapping each post in the snapshot to its own Post item, where in the constructor it needs to run a further async call to extract the username. Am I missing something?
Note: even making the Future.wait() await returns null, it just also doesn't return a List of type Future so I can't use it in the FutureBuilder either.
Edit 1:
It turns out that futurePosts is actually an Instance of 'Future<List<Post>>', but when accessing the data within the FutureBuilder, snapshot.data is null:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Feed'),
),
body: FutureBuilder(
future: getPosts(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
print(snapshot.data);
return postsToColumn(context, snapshot.data as List<Post>);
}
return const Center(
child: CircularProgressIndicator(),
);
}
),
);
}
Future.value(allData)Future.waitnever returns null. At the very least it returns a future that returns an empty list. IfgetPostswould be able to return null the compiler would already complain also and you couldn't even run your app. What do you exactly mean with "it returns null"? because that simply is impossible[Instance of 'Future<Post>', Instance of 'Future<Post>', Instance of 'Future<Post>']print(futurePosts)I getInstance of 'Future<List<Post>>'. Thenullappears to actually come in theFutureBuilderitself, when Iprint(snapshot.data), so it appears as if thesnapshotitself is the issue? Perhaps I'm using it incorrectly.