React表格菜单按钮异常:所有行均显示最后一行数据
React表格菜单显示最后一行信息的解决方案
问题核心是所有行共用了同一个状态和重复的DOM标识:
- 全局
open布尔值和anchorEl变量被所有菜单绑定,点击任意按钮都会触发同一个状态,而循环结束后row.videoId会保留最后一行的值,导致菜单显示最后一行数据 - 按钮和菜单的ID(
long-button、long-menu)固定重复,浏览器无法区分不同行的菜单组件
解决思路
- 将全局
open状态改为存储当前激活的videoId(初始为null),精准控制单一行菜单的显示 - 给每一行的按钮和菜单设置唯一ID,用
row.videoId作为标识后缀 - 修改菜单触发逻辑,绑定当前行的
videoId
修改后的代码示例
// 组件内状态定义修改 const [selectedVideoId, setSelectedVideoId] = useState(null); const [anchorEl, setAnchorEl] = useState(null); // 菜单点击处理函数,接收当前行的videoId和事件对象 const handleOptionsClick = (event, videoId) => { setAnchorEl(event.currentTarget); setSelectedVideoId(videoId); }; // 菜单关闭函数 const handleClose = () => { setAnchorEl(null); setSelectedVideoId(null); }; // 表格主体代码修改 <TableBody> {visibleRows.map((row, index) => { const videoId = row.videoId; const isItemSelected = isSelected(row.videoId.toString()); const labelId = `enhanced-table-checkbox-${index}-${row.videoId}`; // 生成当前行按钮和菜单的唯一ID const buttonId = `long-button-${videoId}`; const menuId = `long-menu-${videoId}`; return ( <TableRow key={row.videoId as string} hover onClick={(event) => handleClick(event, row.videoId.toString())} role="checkbox" tabIndex={-1} sx={{ cursor: 'pointer' }} > <TableCell align="left" sx={{ maxWidth: 154, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', }} > {row.videoId} <IconButton aria-label="more" id={buttonId} aria-controls={selectedVideoId === videoId ? menuId : undefined} aria-expanded={selectedVideoId === videoId ? 'true' : undefined} aria-haspopup="true" onClick={(e) => handleOptionsClick(e, videoId)} > <MoreVertIcon /> </IconButton> <Menu id={menuId} MenuListProps={{ 'aria-labelledby': buttonId, }} anchorEl={anchorEl} open={selectedVideoId === videoId} onClose={handleClose} PaperProps={{ style: { maxHeight: ITEM_HEIGHT * 4.5, width: '20ch', }, }} > <MenuItem key="edit" onClick={handleClose}> <a href={`https://webiste.com/${row.videoId}/edit`}>{row.videoId}</a> </MenuItem> </Menu> </TableCell> </TableRow> ); })} {emptyRows > 0 && ( <TableRow style={{ height: 53 * emptyRows, }} > <TableCell colSpan={6} /> </TableRow> )} </TableBody>
关键改动说明
- 用
selectedVideoId替代原open状态,通过匹配当前行ID控制菜单显示 - 按钮和菜单ID加入
videoId后缀,保证DOM标识唯一 - 点击按钮时传入当前行
videoId,绑定激活状态 - 菜单
open条件改为判断selectedVideoId与当前行ID是否匹配
内容的提问来源于stack exchange,提问作者Exorcismus
相关产品推荐
相关产品推荐

