Javascript 在我的数组中推多个对象会擦除数组中以前的所有对象(使用挂钩进行反应)
我想在我的数组中推一个对象,在forEach的每个循环中, 但在每次循环中,我的数组似乎都变为空,所以我的数组中只有最后一个被推入的对象 我的代码中的这一行似乎不起作用:Javascript 在我的数组中推多个对象会擦除数组中以前的所有对象(使用挂钩进行反应),javascript,reactjs,axios,Javascript,Reactjs,Axios,我想在我的数组中推一个对象,在forEach的每个循环中, 但在每次循环中,我的数组似乎都变为空,所以我的数组中只有最后一个被推入的对象 我的代码中的这一行似乎不起作用: setSeriesLikedDetails([...seriesLikedDetails, dataSerieDetail.data]); 因为当我做这件事的时候 console.log("seriesLikedDetails ", seriesLikedDetails); 我总是在数组中有一个对象(最后一个推入的对象),
setSeriesLikedDetails([...seriesLikedDetails, dataSerieDetail.data]);
因为当我做这件事的时候
console.log("seriesLikedDetails ", seriesLikedDetails);
我总是在数组中有一个对象(最后一个推入的对象),而不是一个对象数组
以下是组件代码的一部分:
function Likes(props) {
const [moviesLiked, setMoviesLiked] = useState([]);
const [seriesLiked, setSeriesLiked] = useState([]);
const [moviesLikedDetails, setMoviesLikedDetails] = useState([]);
const [seriesLikedDetails, setSeriesLikedDetails] = useState([]);
useEffect(() => {
loadMoviesLikedDetails();
loadSeriesLikedDetails();
}, [moviesLiked, seriesLiked]);
async function loadMoviesLikedDetails() {
setMoviesLikedDetails([]);
moviesLiked.forEach(async movie => {
try {
const dataMovieDetail = await axios.get(
`https://api.themoviedb.org/3/movie/${movie}?api_key=381e8c936f62f2ab614e9f29cad6630f&language=fr`
);
console.log("MovieDetail ", dataMovieDetail.data);
setMoviesLikedDetails(movieDetails => [
...movieDetails,
dataMovieDetail.data
]);
} catch (error) {
console.error(error);
}
});
}
async function loadSeriesLikedDetails() {
setSeriesLikedDetails([]);
seriesLiked.forEach(async serie => {
try {
const dataSerieDetail = await axios.get(
`https://api.themoviedb.org/3/tv/${serie}?api_key=381e8c936f62f2ab614e9f29cad6630f&language=fr`
);
console.log("SerieDetail ", dataSerieDetail.data);
setSeriesLikedDetails(serieDetails => [
...serieDetails,
dataSerieDetail.data
]);
} catch (error) {
console.error(error);
}
});
}
这很可能是因为在forEach回调中,seriesLikedDetails始终是相同的引用,而setSeriesLikedDetails会更改要跟踪的实际数组 因此,在forEach的最后一次迭代中,您只需将最后一个值添加到初始数组,并将其设置为当前数组 相反,通过这样做:
async function loadSeriesLikedDetails() {
const newArray = [...seriesLikedDetails];
const promises = seriesLiked.map(async serie => {
try {
const dataSerieDetail = await axios.get(
`https://api.themoviedb.org/3/tv/${serie}?api_key=381e8c936f62f2ab614e9f29cad6630f&language=fr`
);
console.log("SerieDetail ", dataSerieDetail.data);
newArray.push(dataSerieDetail.data);
} catch (error) {
console.error(error);
}
});
Promise.all(promises).then(()=>setSeriesLikedDetails(newArray));
}
您将使用正确的新值更新状态一次。这很可能是因为在forEach回调中,seriesLikedDetails始终是相同的引用,而setSeriesLikedDetails会更改您要跟踪的实际数组 因此,在forEach的最后一次迭代中,您只需将最后一个值添加到初始数组,并将其设置为当前数组 相反,通过这样做:
async function loadSeriesLikedDetails() {
const newArray = [...seriesLikedDetails];
const promises = seriesLiked.map(async serie => {
try {
const dataSerieDetail = await axios.get(
`https://api.themoviedb.org/3/tv/${serie}?api_key=381e8c936f62f2ab614e9f29cad6630f&language=fr`
);
console.log("SerieDetail ", dataSerieDetail.data);
newArray.push(dataSerieDetail.data);
} catch (error) {
console.error(error);
}
});
Promise.all(promises).then(()=>setSeriesLikedDetails(newArray));
}
您将使用正确的新值更新状态一次。
系列详细信息将在此处缓存,并且仅在组件重新加载时更新。由于在重新加载期间不会再次调用loadSeriesLikedDetails()
,因此初始seriesLikedDetails
仍然是一个空数组
让我们看一下内部发生了什么(您的代码):
- 组件被渲染
useffect()
“启动并运行”
- 正在进行Axios调用,然后调用
setSeriesIkedDetails()
seriesLikedDetails
现在包含一个元素
- 组件现在重新招标。重新检索组件时,
loadSeriesLikedDetails()代码>不是被称为
系列喜欢的
没有改变
seriesLikedDetails
的当前值仍然是空数组,因为这仍然发生在原始渲染中Promise.all
,因为您可能希望在更新到来时对UI进行顺序更新。在这种情况下,您可以将setSeriesIkedDetails
与函数一起使用,以始终拉取当前值以更新它:
function Likes(props) {
const [moviesLiked, setMoviesLiked] = useState([]);
const [seriesLiked, setSeriesLiked] = useState([]);
const [moviesLikedDetails, setMoviesLikedDetails] = useState([]);
const [seriesLikedDetails, setSeriesLikedDetails] = useState([]);
useEffect(() => {
loadSeriesLikedDetails();
}, [seriesLiked]);
useEffect(() => {
console.log("seriesLikedDetails ", seriesLikedDetails);
}, [seriesLikedDetails]);
async function loadSeriesLikedDetails() {
seriesLiked.forEach(async serie => {
try {
const dataSerieDetail = await axios.get(
`https://api.themoviedb.org/3/tv/${serie}?api_key=381e8c936f62f2ab614e9f29cad6630f&language=fr`
);
console.log("SerieDetail ", dataSerieDetail.data);
setSeriesLikedDetails(currSeriesDetails => [...currSeriesDetails, dataSerieDetail.data]);
} catch (error) {
console.error(error);
}
});
}
这就像传递函数一样简单:
setSeriesLikedDetails(currSeriesDetails => [...currSeriesDetails, dataSerieDetail.data]);
此外,您可能还希望在开始时重置阵列(或写入阵列,以便只获取尚未获取的电影/系列):
请参阅部分文档。
系列详细信息将在此处缓存,并且仅在组件重新加载时更新。由于在重新加载期间不会再次调用loadSeriesLikedDetails()
,因此初始seriesLikedDetails
仍然是一个空数组
让我们看一下内部发生了什么(您的代码):
- 组件被渲染
useffect()
“启动并运行”
- 正在进行Axios调用,然后调用
setSeriesIkedDetails()
seriesLikedDetails
现在包含一个元素
- 组件现在重新招标。重新检索组件时,
loadSeriesLikedDetails()代码>不是被称为
系列喜欢的
没有改变
seriesLikedDetails
的当前值仍然是空数组,因为这仍然发生在原始渲染中Promise.all
,因为您可能希望在更新到来时对UI进行顺序更新。在这种情况下,您可以将setSeriesIkedDetails
与函数一起使用,以始终拉取当前值以更新它:
function Likes(props) {
const [moviesLiked, setMoviesLiked] = useState([]);
const [seriesLiked, setSeriesLiked] = useState([]);
const [moviesLikedDetails, setMoviesLikedDetails] = useState([]);
const [seriesLikedDetails, setSeriesLikedDetails] = useState([]);
useEffect(() => {
loadSeriesLikedDetails();
}, [seriesLiked]);
useEffect(() => {
console.log("seriesLikedDetails ", seriesLikedDetails);
}, [seriesLikedDetails]);
async function loadSeriesLikedDetails() {
seriesLiked.forEach(async serie => {
try {
const dataSerieDetail = await axios.get(
`https://api.themoviedb.org/3/tv/${serie}?api_key=381e8c936f62f2ab614e9f29cad6630f&language=fr`
);
console.log("SerieDetail ", dataSerieDetail.data);
setSeriesLikedDetails(currSeriesDetails => [...currSeriesDetails, dataSerieDetail.data]);
} catch (error) {
console.error(error);
}
});
}
这就像传递函数一样简单:
setSeriesLikedDetails(currSeriesDetails => [...currSeriesDetails, dataSerieDetail.data]);
此外,您可能还希望在开始时重置阵列(或写入阵列,以便只获取尚未获取的电影/系列):
请参阅部分文档。完美,它现在可以与您编辑的答案一起使用!谢谢,如果它不能解释你最初的问题,弗兰克兹下面的答案更适合你的需要。好的,np,你能接受你的答案吗,因为我对另一个答案有一个问题:完美,它现在适用于你编辑的答案!谢谢,如果它不能解释你最初的问题,弗兰克兹下面的答案更适合你的需要。好的,np,你能让你的答案,因为我对另一个答案有一个问题:DMy回答交易和解释OP的范围问题,但这应该是怎么做的。你好,我试过你的答案,它非常适合电视节目,但对于电影,forEach在moviesLiked中每项完成2次(因为事实上我必须为电影和电视节目这样做)我在moviesLiked中有3项,但forEach是6次,而不是3次(每项2次)setMoviesLikedDetails(currDetails=>[…currDetails,dataMovieDetail.data]);发布您的更新代码。此外,请尝试使用
currMovieDetails
以避免名称重叠。@请参阅我的更新答案。由于@remix32的代码使用了Promise.all()
并随后更新了所有内容,因此它将覆盖可能存在的任何细节。你可能想在loadSeriesLikedDetails()
开始时重置数组。我发布了更新的代码,这与我为电影复制的系列是一样的。因此,在渲染中,我映射到moviesLikeDetails,我在doubleMy Response中得到了每一部电影,并解释了OP的范围问题,但这应该是如何做到的。您好,我尝试了您的答案,它对电视节目非常有效,但对于电影来说,forEach似乎在moviesLiked中每项做了2次(因为事实上我不得不这么做)