Reputation: 43
I am a junior dev and at this moment am working on a forum done with ReactJS and Firebase.
I am having an issue with the dynamic read of subcollections.
Here is a screen shot of my Firestore.
Topics have each a Topic document and a posts collection(well subcollection).
I have tried many ways to retrieve the data from subcollections dynamically, but none works. Been diving in stackoverflow, in articles but I am stuck. The queries for the Topics work well, and the posts too but not dynamically. If you could help I will be very grateful because searching for a solution has lasted for a while, so Thank you in advance.
These are my imports:
import firebase from 'firebase';
import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';
and in separate file there is the firebaseConfig and also firebase is initialized.
These are the queries:
const db = firebase.firestore();
const dbPostsCollection = db.collection("topics");
const [data, setData] = useState([]);
My first and main query, which brings me closest to what I want as a result but can’t retrieve the data.
useEffect(() => {
dbPostsCollection.get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id, " => ", doc.data());
console.log(doc.id, " => ", db.collection("posts"));
});
});
}, []);
There is no error, below you’ll see an screenshot of the console.logs
Second query:
useEffect(() => {
dbPostsCollection
.get()
.then(function (Document) {
Document.forEach((subCollectionSnapshot) => {
const postsData = subCollectionSnapshot.map(subcollection =>
subcollection.data())
console.log(postsData); // array of posts objects
setData(postsData);
});
}
);
}, []);
the error message: Unhandled Rejection (TypeError): subCollectionSnapshot.map is not a function
And the last query (there are more than 3 but I’ll spare you from reading all my trials):
useEffect(() => {
dbPostsCollection
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log(doc.id, " => ", doc.data());
console.log(doc.id, " => ", db.collection("posts").get().then(querySnapshot => {
const data = querySnapshot.docs.map(doc => doc.data());
console.log(data);
}));
})
});
}, []);
This query doesn’t return the Promise result, the result is undefined. Thank you again for your help!
Upvotes: 0
Views: 226
Reputation: 3499
useEffect()
is by definition and requirement a SYNCHRONOUS function, and Firestore operations are ASYNCHRONOUS - likely your useEffect()
is exiting before any Firestore activity occurs.
A common hack is to create a self-executing closure inside the useEffect()
to effectively "spawn" a thread:
useEffect(() => {
(async () => {
await dbPostsCollection
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
console.log(doc.id, " => ", doc.data());
console.log(doc.id, " => ", db.collection("posts").get().then(querySnapshot => {
const data = querySnapshot.docs.map(doc => doc.data());
console.log(data);
}));
})
});
})();
}, []);
The (async () => {})
returns the anonymous ARROW FUNCTION; the await
indicates to wait for the following commend to execute (effectively waiting for the implied Promise to resolve); the following ()
executes it. The arrow function returns a Promise
, which the useEffect pretty much ignores, but the function does run to completion.
Upvotes: 1