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

React子组件传参异常:所有子组件接收同一最终值问题排查

问题原因

这是典型的JavaScript闭包陷阱:你在forEach循环里声明的position是一个全局(相对于循环)变量,循环里的回调函数捕获的是这个变量的引用,而非每次循环时的数值快照。

因为React的setState是异步操作,当这些回调实际执行时,position已经完成了所有递增操作,最终变成了40。所有<VisitedCountry>组件的position属性都会指向这个最终值,导致子组件拿到的都是40。

解决方案

方案1:使用forEach的索引参数(最直接)

利用forEach的第二个参数(循环索引,从0开始)生成position,索引是每次循环的固定值,不会被后续修改影响:

data.countries.forEach((el, index) => {
  const currentPosition = index + 1; // 索引从0开始,加1得到1-40的序号
  setCountryList(tmpCountry => [...tmpCountry, <VisitedCountry position={currentPosition} />]);
});

方案2:用map替代forEach(React推荐写法)

React中处理数组渲染更推荐用map,它直接返回元素数组,还能避免多次调用setState的问题,同时记得给列表元素加唯一key:

// 一次性生成所有组件,再更新state
const newCountryComponents = data.countries.map((el, index) => {
  // 优先用国家的唯一标识作为key(比如el.id、el.countryCode),没有的话再用index
  return <VisitedCountry key={index} position={index + 1} />;
});
setCountryList(newCountryComponents);

方案3:捕获每次循环的position快照

如果坚持用forEach,可以在循环内部用const捕获当前position的数值快照,避免闭包引用同一个变量:

let position = 1;
data.countries.forEach(el => {
  const currentPos = position; // 捕获当前循环的position值
  setCountryList(tmpCountry => [...tmpCountry, <VisitedCountry position={currentPos} />]);
  position++;
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 00:50:04