I am working with React, and I have a component that gets data from Firebase, which is a list of movies the user has watched.
After getting that data, I loop through that individual movie and get data of the movie. This all happens when the component mount:
useEffect(() => {
getWatched();
}, []);
And getWatched
is the function that gets all the data:
const getWatched = async () => {
try {
const snapShot = await getDocs(
collection(db, "users", auth.currentUser.uid, "Watched")
);
let arr = [];
snapShot.forEach((doc) => {
arr.push(doc.data());
});
let w = [];
arr.forEach((obj) => {
let show = obj.show ? "movie" : "tv";
console.log(obj.id);
const link =
"https://api.themoviedb.org/3/"
show
"/"
obj.id
"?api_key="
process.env.REACT_APP_MOVIE_DB
"&language=en-US";
fetch(link)
.then((response) => response.json())
.then((response) => w.push(response));
});
setWatched(w);
console.log("Got Data");
} catch (error) {
console.log(error);
}
};
And in the return, I am looping through watched and returning divs of the data I have got. I guess I am getting data late. So it is not showing me anything.
CodePudding user response:
It's because setWatched(w)
is being called before the promises resolve. A solution to this is to use a Promise.all()
like so:
const getWatched = async () => {
const innerFetch = async (link) => {
const res = await fetch(link);
const data = await res.json();
return data;
};
try {
const snapShot = await getDocs(
collection(db, "users", auth.currentUser.uid, "Watched")
);
const arr = [];
snapShot.forEach((doc) => {
arr.push(doc.data());
});
const promises = arr.map((obj) => {
let show = obj.show ? "movie" : "tv";
console.log(obj.id);
const link =
"https://api.themoviedb.org/3/"
show
"/"
obj.id
"?api_key="
process.env.REACT_APP_MOVIE_DB
"&language=en-US";
return innerFetch(link);
});
const w = await Promise.all(promises);
setWatched(w);
console.log("Got Data");
} catch (error) {
console.log(error);
}
};
CodePudding user response:
I am satisfied with yousoumar answer. Here I have also tried something.
const getWatched = async () => {
try {
const snapShot = await getDocs(collection(db, "users", auth.currentUser.uid, "Watched"));
let arr = [];
snapShot.forEach((doc) => {
arr.push(doc.data());
})
let w = [];
arr.forEach((obj) => {
let show = obj.show ? "movie" : "tv";
const link = "https://api.themoviedb.org/3/" show "/"
obj.id "?api_key=" process.env.REACT_APP_MOVIE_DB "&language=en-US";
w.push(getData(link));
});
Promise.all(w)
.then(results => {
setWatched(results);
})
.catch((err) => console.log(err));
} catch (error) {
console.log(error);
}
}
The main idea here as yousoumar said is using Promise.all
.