I have this Firebase Firestore query set up in my useEffect
hook:
const [favorites, setFavorites] = useState([]);
const { user, setUser } = useContext(AuthenticatedUserContext);
const getUserFavorites = async () => {
const favoritesRef = collection(db, "favorites");
const q = query(favoritesRef, where("userId", "==", user.uid));
const querySnapshot = await getDocs(q);
const fetchedFavorites = [];
querySnapshot.forEach(async (document) => {
const docRef = doc(db, "receipes", document.data().recipeId);
const docSnap = await getDoc(docRef);
const data = docSnap.data();
fetchedFavorites.push(data);
});
setFavorites(fetchedFavorites);
console.log("favorites " favorites);
};
useEffect(() => {
getUserFavorites();
}, []);
Upon first render of the page the favorites
will be []
and after a re-render it will be populated. When logging within the forEach
I can see that the query is working, so I suspect the async forEach
being the culprit here. How can I fix this?
CodePudding user response:
Yes, you should not use async
function with a forEach()
loop. You can use a for-of
loop with the same code or use Promise.all()
as shown below:
const getUserFavorites = async () => {
const favoritesRef = collection(db, "favorites");
const q = query(favoritesRef, where("userId", "==", user.uid));
const querySnapshot = await getDocs(q);
const favPromises = querySnapshot.docs.map((d) => getDoc(doc(db, "receipes", d.data().recipeId)))
const fetchedFavs = (await Promise.all(favPromises)).map((fav) => fav.data());
setFavorites(fetchedFavs);
console.log("favorites " fetchedFavs);
};
Also checkout: Using async/await with a forEach loop for more information.