在function项目中,我有一个带有一系列游戏的状态gameResults,并且我有一个函数来根据查询获取游戏列表:
useEffect(() => {
const timeoutId = setTimeout(() => {
if (gameQuery.length > 0) {
axios.get(`/api/games/${gameQuery}`).then((response) => {
const igdbGames: IGDBGame[] = response.data.games;
const formatedGames = formatGames(igdbGames);
setGameResults(formatedGames);
});
}
}, 300);
return () => clearTimeout(timeoutId);
}, [gameQuery]);对于每一个游戏,我没有封面,所以我得到了每个游戏的封面:
const loadGamesImages = async () => {
for (let i = 0; i < gameResults.length; i++) {
axios
.get(`/api/cover/${gameResults[i].id}`)
.then((response) => {
const coverUrl: IGDBCover = response.data.covers[0];
const newGame = {
...gameResults[i],
cover: coverUrl.url.replace("//", "https://"),
};
const newGames = gameResults.filter(
(game: Game) => game.id !== newGame.id
);
setGameResults([...newGames, newGame]);
})
.catch((error) => {
console.log("error", error);
});
await sleep(300);
}
console.log("finish");
};
useEffect(() => {
loadGamesImages();
}, [gameResults.length]);这是我的问题:当响应更新状态时,旧状态不再存在。我解释说:对于第一张封面,新的州有第一场比赛是可以的。但是当他为第二个游戏建立一个新的状态时,你可以看到我得到了gameResults状态,但是在这个游戏中,第一个游戏已经没有掩护了。
结果如下:

我做错了什么?
发布于 2021-02-25 15:05:29
在有状态gameResults的初始绑定过程中,每个循环异步调用都会关闭,而gameResults从空开始。例如,对于解决问题的第一个承诺,以下一行:
const newGames = gameResults.filter(
(game: Game) => game.id !== newGame.id
);
setGameResults([...newGames, newGame]);让gameResults引用空数组,这样setGameResults就可以正确地扩展空数组和刚刚添加的newGame。
但是,在进一步的承诺解决方案中,它们还关闭了最初为空的gameResults --所有异步调用都发生在组件重新呈现之前。
相反,使用回调,这样异步调用就不会相互覆盖:
setGameResults((gameResults) => {
const newGames = gameResults.filter(
(game) => game.id !== newGame.id
);
return [...newGames, newGame];
});(还请注意,不需要显式地注意TS已经可以自动推断的参数的类型:(game: Game)可以是game)
一旦这起作用,我还建议调整您的代码,以便当效果钩子再次运行时,只包含尚未被检索但再次被请求的内容。这将避免不必要的重复请求。
https://stackoverflow.com/questions/66371048
复制相似问题