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

React数组逆序填充问题:首次渲染顺序错误刷新后正常如何解决

问题原因
  • 核心是异步请求的返回顺序不可控:你在forEach循环中并行发起多个getProducts接口请求,每个请求的响应时间受网络、服务端处理速度影响,哪个请求先返回,就会先执行setRows将对应数据插入数组,最终rows的顺序是接口响应的先后顺序,和你发起请求的顺序无关。
  • 刷新后顺序正确是巧合:大概率是刷新时接口命中了浏览器缓存,先发的请求优先从缓存读取返回,刚好匹配了你期望的顺序,属于不稳定的偶然现象。
修复方案

有两种常用修复方案,可根据场景选择:

方案1:并发请求+统一处理(推荐,性能更高)

先收集所有请求,用Promise.all等待全部请求完成后,按发起请求的原始顺序统一更新rows,既保证顺序正确,又不会损失请求并发性能。
修改后代码如下:

// 调整getProducts,直接返回响应数据,不单独更新状态
const getProducts = async (data) => {
  try {
    const response = await productServices.getProductsByTakeoffWizardStep(data);
    return response.data;
  } catch (error) {
    console.log(error.response);
    return []; // 错误兜底,避免Promise.all终止
  }
};

const getTakeoffIDs = async () => {
  var i = 1;
  try {
    const response = await takeoffServices.getTakeoffSteps(5);
    const productRequests = []; // 收集所有产品请求
    response.data.forEach((element) => {
      setSteps((steps) => [...steps, element.description]);
      setStepsID((stepsID) => [...stepsID, element.stepID]);
      var data = { StepID: element.stepID, TakeoffID: 4 };
      productRequests.push(getProducts(data)); // 收集请求
      setStepSequence((stepSequence) => [
        ...stepSequence,
        "Step " + i + "",
      ]);
      i = i + 1;
    });
    // 等待所有请求完成,结果顺序和请求发起顺序完全一致
    const allProducts = await Promise.all(productRequests);
    setRows(allProducts); // 一次性更新rows
  } catch (error) {
    console.log(error.response);
  }
};

useEffect(() => {
  setSteps([]);
  setStepsID([]);
  setRows([]);
  getTakeoffIDs();
}, []);

方案2:串行请求(简单直接,性能略低)

如果请求量很小,也可以选择串行发起请求,等前一个请求完成后再发起下一个,保证插入顺序和期望一致:
修改后核心逻辑:

const getTakeoffIDs = async () => {
  var i = 1;
  try {
    const response = await takeoffServices.getTakeoffSteps(5);
    // 把forEach改为for...of,支持await串行执行
    for (const element of response.data) {
      setSteps((steps) => [...steps, element.description]);
      setStepsID((stepsID) => [...stepsID, element.stepID]);
      var data = { StepID: element.stepID, TakeoffID: 4 };
      await getProducts(data); // 等待当前请求完成再执行后续逻辑
      setStepSequence((stepSequence) => [
        ...stepSequence,
        "Step " + i + "",
      ]);
      i = i + 1;
    }
  } catch (error) {
    console.log(error.response);
  }
};

内容的提问来源于stack exchange,提问作者Selim Choueiter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 07:45:03