React中Map渲染的Checkbox如何实现各商品项独立选中状态
解决商品项与人员选中状态独立的问题
你的问题核心是选中状态没有和具体商品项绑定,只用一个全局数组记录人员索引,导致所有商品项共用同一套选中状态。下面是具体修复方案:
1. 重构状态结构
把原来的visibleDivIndices从数组改成对象,用商品项的id作为键,对应值是该商品下选中的人员索引数组,让每个商品的选中状态完全独立:
const [visibleDivIndices, setVisibleDivIndices] = useState({});
2. 修改复选框事件处理函数
更新handleCheckboxChange,让它接收商品id和人员索引,针对对应商品的选中列表做修改:
const handleCheckboxChange = (foodId, personIndex) => { setVisibleDivIndices(prev => { // 获取当前商品已选中的人员列表,无数据则初始化空数组 const currentSelected = prev[foodId] || []; return { ...prev, [foodId]: currentSelected.includes(personIndex) // 已选中则移除该索引 ? currentSelected.filter(idx => idx !== personIndex) // 未选中则添加该索引 : [...currentSelected, personIndex] }; }); };
3. 调整渲染逻辑
遍历人员列表时,基于当前商品的id判断是否显示对应内容,不再依赖全局数组:
{FoodWeight.map(el => { /* THIS IS THE PRODUCT ITEM MAP */ if (el.id == checkbox.id) { let number = el.Quantity; // 获取当前商品对应的选中人员索引列表 const currentSelectedPersons = visibleDivIndices[el.id] || []; return ( <div className="selection-wrapper" key={el.id}> {/* 给外层容器加唯一key */} <TextField value={number} InputLabelProps={{ shrink: true }} id="standard-basic" label="Qty" name="quantity" onWheel={(e) => e.target.blur()} className="second-selection-qty" onChange={e => quantityfunctionFood(e.currentTarget.value, checkbox.id, checkbox)} type="Number" variant="outlined" /> {tr?.map((item, i) => { /* THIS IS THE PERSON MAP */ return ( <div key={`${el.id}-${item.Name}-${i}`}> {/* 键包含商品id,保证全局唯一 */} <FormControlLabel value={`${item.Name}-${i}`} control={<Checkbox onChange={() => handleCheckboxChange(el.id, i)} />} label={item.Name} /> {currentSelectedPersons.includes(i) && ( <> {getselecteddata.map((els, idx) => ( <div key={idx}>This content should only be displayed after checking the checkbox for the person</div> ))} </> )} </div> )})} </div> ) } return null; // 匹配不到时返回null })}
额外修复点
- 原来的
filter((i) => i !== i)是无效代码,会过滤掉所有元素,已修正为filter(idx => idx !== personIndex) - 给循环生成的元素添加包含商品id的唯一key,避免React渲染警告
修改后,每个商品项的人员选中状态完全独立,初始时所有商品仅显示人员列表、无选中状态。
内容的提问来源于stack exchange,提问作者Paul VI
相关产品推荐
相关产品推荐

