You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React调用PokeAPI开发宝可梦图鉴时map渲染元素乱序问题求解

问题原因

  • 乱序问题确实和网络/设备性能直接相关:代码中对每只宝可梦的详情请求是并行发起的异步fetch,没有等待所有请求返回就单个更新listPokemon数组,哪个请求先返回就先把对应数据插入数组末尾,最终数组顺序和请求返回顺序完全一致,和初始的列表顺序无关。手机端网络波动更大、JS线程调度优先级更低,所以乱序出现概率更高。
  • 额外隐藏问题:setLoading(false)写在fetch逻辑外层,会在请求刚发起时就直接关闭加载状态,而非等所有数据加载完成后才关闭。
  • 原有代码中包裹data.results的Promise.all是冗余逻辑,没有实际作用。

修复方案

将单个请求返回就更新数组的逻辑改为等待所有详情请求完成后,按初始顺序统一更新数组即可,Promise.all返回结果的顺序和传入的Promise数组顺序完全一致,不受请求返回先后影响,修改后的getAllPokemon代码如下:

function getAllPokemon(url) {
  fetch(url)
    .then((res) => res.json())
    .then(async (data) => {
      // 按原顺序发起所有详情请求,收集Promise
      const detailPromises = data.results.map((res) => 
        fetch(res.url).then((resp) => resp.json())
      );
      // 等待所有请求完成,返回顺序和初始data.results顺序完全一致
      const allDetails = await Promise.all(detailPromises);
      // 按原顺序组装新数据
      const newPokemonList = data.results.map((res, index) => {
        const detail = allDetails[index];
        return {
          id: detail.id,
          name: res.name,
          url: res.url,
          image_url: detail.sprites.other["official-artwork"].front_default,
        };
      });
      // 统一更新数组
      setListPokemon((listPokemon) => [...listPokemon, ...newPokemonList]);
      // 所有数据加载完成后再关闭loading
      setLoading(false);
    });
}
  • 若要追求更稳妥的渲染顺序,也可以在渲染前对listPokemon按id升序排序,修改渲染代码即可:
{listPokemon.sort((a,b) => a.id - b.id).map((p) => (
  <Grid>
      <Card>
        <CardMedia
          component="img"
          image={p.image_url}
          alt={p.name}
        />
        <CardContent>
          {p.id}.{setCap(p.name)}
        </CardContent>
      </Card>
  </Grid>
))}

内容的提问来源于stack exchange,提问作者Tuan Le

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 00:06:05