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

如何按id匹配两个接口数据为循环渲染的ShiftComponent传参

核心问题说明

你当前的实现存在两个核心错误:

  1. 循环调用第二个API时,每次请求成功都直接执行setValue(resp.data),会持续覆盖前一次的请求结果,最终value状态只会保留最后一个请求的返回值,无法存储所有id对应的数据
  2. 渲染时嵌套遍历两个数组会产生笛卡尔积,自然会出现重复渲染问题,大数据量场景下还会严重拖累性能

解决方案

步骤1:调整value状态的存储结构

把value从数组/单个对象改为以id为键的映射对象,可以实现O(1)时间的id匹配,适配大数据量场景的性能要求:

// 初始化状态时使用空对象
const [valueMap, setValueMap] = useState<Record<string | number, {name: string, address: {state: string, city: string}}>>({})

步骤2:优化第二个API的批量调用逻辑

使用Promise.all统一处理批量请求,避免循环调用的竞态问题,请求完成后一次性更新映射对象:

const fetchValueList = async () => {
  try {
    // 生成所有请求的Promise数组
    const requestList = id.map(itemId => ApiCall.get(`${Url}value/${itemId}`))
    // 等待所有请求完成
    const respList = await Promise.all(requestList)
    // 把返回结果转换为id为键的映射对象
    const resultMap = respList.reduce((map, resp) => {
      const data = resp.data
      map[data.id] = data
      return map
    }, {})
    // 一次性更新状态
    setValueMap(resultMap)
  } catch (err) {
    console.log(err)
    Alert.alert('Error', '数据获取失败')
  }
}

如果需要兼容部分请求失败不影响整体使用的场景,可以将单个请求包一层错误捕获,把Promise.all替换为Promise.allSettled即可。

步骤3:渲染时直接匹配id取值

不需要嵌套遍历,直接用shift列表的item.id去映射对象中取对应数据即可:

{shift.map((item: any) => (
  <ShiftComponent
    key={item.id} // 不要用index作为key,使用唯一id避免渲染异常
    Name={valueMap[item.id]?.name || '默认名称'}
    StartTime={item.expected.start_time}
    EndTime={item.expected.end_time}
    Address={valueMap[item.id]?.address ? `${valueMap[item.id].address.city} ${valueMap[item.id].address.state}` : '默认地址'}
  />
))}

如果需要避免数据加载过程中出现空值闪烁,可以额外加一个加载状态判断,等所有数据返回后再渲染组件。


内容的提问来源于stack exchange,提问作者pratteek shaurya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 20:45:03