[英]Fetching data in a loop and then calling setState not working in React
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.我正在使用 React,我有一个组件可以从 Firebase 获取数据,这是用户看过的电影列表。
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:而
getWatched
就是获取所有数据的function:
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.在返回时,我正在循环查看并返回我所获得数据的 div。 I guess I am getting data late.
我想我迟到了数据。 So it is not showing me anything.
所以它没有向我展示任何东西。
It's because setWatched(w)
is being called before the promises resolve.这是因为
setWatched(w)
在承诺解决之前被调用。 A solution to this is to use a Promise.all()
like so:一个解决方案是像这样使用
Promise.all()
:
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);
}
};
I am satisfied with yousoumar answer.我对 yousoumar 的回答很满意。 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
.正如 yousoumar 所说,这里的主要思想是使用
Promise.all
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.