I need some help to understand why this is acting this way to learn better:
I have a simple funciton to fetch data from database, but when I try to push the data in the second foreach loop, I am unable to render the items by using array.map as if objects were pushed in the first forEach.
Here is the code and I will attach some screen shots of the outcome I expect.
const fetchPrices = async () => {
try {
let data=[]
const products = query(collection(db, 'products'), where("active", "==", true));
const querySnapshot = await getDocs(products);
querySnapshot.forEach(async (doc) => {
//works fine if I do it in this forEach
//let obj = {planId: doc.id, planName: doc.data().name}
const priceSnap = await getDocs(collection(doc.ref, 'prices'));
priceSnap.forEach( (price) => {
//this is where the challenge comes from...
let obj = {planId: doc.id, planName: doc.data().name, priceId: price.id, priceAmount:price.data().unit_amount}
data.push(obj);
});
//data.push(obj);
});
console.log(data);
let listitems = data.map((d) => <MenuItem key={d.planId} value={d.priceId}>{d.planName}</MenuItem>)
setSubscriptionPlans(listitems);
} catch (err) {
console.error(err);
}
};
what I expect to get: (what I get when I push the obj in the first loop)
what I get when pushing the obj from the second one:
Please feel free to let me know if you need more info.
Thanks,
Your problem is here
priceSnap.forEach( (price) => {
//this is where the challenge comes from...
let obj = {planId: doc.id, planName: doc.data().name, priceId: price.id, priceAmount:price.data().unit_amount}
data.push(obj);
});
console.log(data);
This inner forEach
would handle a bunch of promises and will not actually force the outer block of code to wait until it finishes. It will fire the forEach and continue outside of this block of code to the outer console.log(data)
while the loop still executes.
Try with the following code instead.
const fetchPrices = async () => {
try {
let data=[]
const products = query(collection(db, 'products'), where("active", "==", true));
const querySnapshot = await getDocs(products);
for await (const doc of querySnapshot) {
for await (const price of getDocs(collection(doc.ref, 'prices')) ) {
let obj = {planId: doc.id, planName: doc.data().name, priceId: price.id, priceAmount:price.data().unit_amount}
data.push(obj);
}
}
console.log(data);
let listitems = data.map((d) => <MenuItem key={d.planId} value={d.priceId}>{d.planName}</MenuItem>)
setSubscriptionPlans(listitems);
} catch (err) {
console.error(err);
}
};