React map渲染列表后所有MenuItem点击均返回数组最后一项问题求解
问题原因及修复方案
核心问题
你所有循环生成的Menu组件共用了同一组open、anchorEl状态,没有和列表项的索引做绑定:
- 点击任意列表项的
IconButton触发状态更新后,所有列表项的Menu都会同时被设置为打开状态 - 按渲染顺序,最后一个列表项的
Menu会堆叠在最上层,你点击菜单项时实际触发的是最后一项Menu内的MenuItem点击事件,所以永远返回数组最后一项的note值
次要问题(可顺带修复)
ListItemButton的点击回调参数写错了,你定义的(idx) => handleList(note, idx)里的idx是点击事件对象,不是你循环生成的索引值,调用handleList时拿到的索引会不符合预期。
修复步骤
- 调整状态定义,新增存储当前激活菜单项索引的状态
// 替换原来的open状态 const [activeIdx, setActiveIdx] = useState(null); const [anchorEl, setAnchorEl] = useState(null);
- 修改
handleClick和handleClose方法
const handleClick = (event, idx) => { setAnchorEl(event.currentTarget); setActiveIdx(idx); }; const handleClose = () => { setAnchorEl(null); setActiveIdx(null); };
- 修改循环内的组件绑定逻辑
{results.map((note, idx) => { return( <Grid container spacing={0} key={idx}> <Grid item sm={11} md={11} lg={11}> {/* 修正ListItemButton的点击回调参数 */} <ListItemButton className={classes.list} onClick={() => handleList(note, idx)} selectedindex={idx} > <ListItemText primary={note} secondary="date"/> </ListItemButton> </Grid> <Grid item sm={1} md={1} lg={1}> <IconButton className={classes.tagButton} // 点击时传入当前索引 onClick={(e) => handleClick(e, idx)} aria-controls="basic-menu" aria-haspopup="true" aria-expanded={activeIdx === idx ? 'true' : undefined} > <LabelIcon className={classes.listTag}/> </IconButton> <Menu id={String(idx)} anchorEl={anchorEl} // 只有当前索引等于激活索引时才打开菜单 open={activeIdx === idx} onClose={handleClose} MenuListProps={{ 'aria-labelledby': 'basic-button', }} > <MenuItem onClick={() => changeLabel(note, "#00AF54")}> <Box sx={{ width: "2vh", height: "2vh", backgroundColor: "#00AF54"}}></Box> <p>green</p> </MenuItem> </Menu> </Grid> </Grid> ) })}
内容的提问来源于stack exchange,提问作者Caio Ishikawa
相关产品推荐
相关产品推荐

