首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >保持旧状态-新状态未更新

保持旧状态-新状态未更新
EN

Stack Overflow用户
提问于 2021-02-25 15:00:31
回答 1查看 35关注 0票数 0

在function项目中,我有一个带有一系列游戏的状态gameResults,并且我有一个函数来根据查询获取游戏列表:

代码语言:javascript
复制
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]);

对于每一个游戏,我没有封面,所以我得到了每个游戏的封面:

代码语言:javascript
复制
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状态,但是在这个游戏中,第一个游戏已经没有掩护了。

结果如下:

我做错了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-25 15:05:29

在有状态gameResults的初始绑定过程中,每个循环异步调用都会关闭,而gameResults从空开始。例如,对于解决问题的第一个承诺,以下一行:

代码语言:javascript
复制
const newGames = gameResults.filter(
    (game: Game) => game.id !== newGame.id
);
setGameResults([...newGames, newGame]);

gameResults引用空数组,这样setGameResults就可以正确地扩展空数组和刚刚添加的newGame

但是,在进一步的承诺解决方案中,它们还关闭了最初为空的gameResults --所有异步调用都发生在组件重新呈现之前。

相反,使用回调,这样异步调用就不会相互覆盖:

代码语言:javascript
复制
setGameResults((gameResults) => {
    const newGames = gameResults.filter(
        (game) => game.id !== newGame.id
    );
    return [...newGames, newGame];
});

(还请注意,不需要显式地注意TS已经可以自动推断的参数的类型:(game: Game)可以是game)

一旦这起作用,我还建议调整您的代码,以便当效果钩子再次运行时,只包含尚未被检索但再次被请求的内容。这将避免不必要的重复请求。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66371048

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档