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

如何在Material UI DataGrid组件的最后一列添加Menu组件?

问题核心原因
  • 所有行的Menu共用同一个布尔状态menuOpen,点击任意行按钮会触发所有行的Menu同时尝试渲染,冲突导致无法正常显示
  • MUI的Menu组件强制要求绑定anchorEl属性来指定弹出位置,缺少该属性就算状态正确也无法正常渲染
  • 直接对原columns数组执行push操作,会修改原数组,可能导致重复添加操作列的异常
修复方案

将原来的布尔状态替换为存储当前触发菜单的锚元素和对应行ID,确保同一时间只有对应行的菜单渲染:

// 替换原有menuOpen相关状态
const [anchorEl, setAnchorEl] = useState(null);
const [activeRowId, setActiveRowId] = useState(null);

const getNewCells = () => {
  // 展开原数组避免修改原数据
  const newCols = [...columns];

  newCols.push({
    field: 'action',
    flex: 1,
    sortable: false,
    filterable: false,
    renderCell: (cell) => {
      // 仅当前行菜单匹配时设置为打开状态
      const isMenuOpen = Boolean(anchorEl) && activeRowId === cell.id;
      return (
        <>
          <Box
            aria-controls={isMenuOpen ? `menu-${cell.id}` : undefined}
            aria-haspopup="true"
            aria-expanded={isMenuOpen ? 'true' : undefined}
            onClick={(e) => {
              setAnchorEl(e.currentTarget);
              setActiveRowId(cell.id);
            }}
            size="small"
            component={Button}
            width="2rem!important"
            height="2rem!important"
            minWidth="2rem!important"
            minHeight="2rem!important"
          >
            <Box
              component={MoreVert}
              width="1.25rem!important"
              height="1.25rem!important"
              position="relative"
              top="2px"
              color={theme.palette.gray[500]}
            />
          </Box>
          <Menu
            id={`menu-${cell.id}`}
            open={isMenuOpen}
            anchorEl={anchorEl}
            onClose={() => {
              setAnchorEl(null);
              setActiveRowId(null);
            }}
            anchorOrigin={{
              vertical: 'bottom',
              horizontal: 'center',
            }}
            transformOrigin={{
              vertical: 'top',
              horizontal: 'center',
            }}
          >
            <MenuItem onClick={() => {
              goToDetail(cell.id);
              setAnchorEl(null);
              setActiveRowId(null);
            }}>详情</MenuItem>
            <MenuItem onClick={() => {
              // 自定义业务逻辑
              setAnchorEl(null);
              setActiveRowId(null);
            }}>跳转至其他页面</MenuItem>
            <MenuItem onClick={() => {
              // 自定义业务逻辑
              setAnchorEl(null);
              setActiveRowId(null);
            }}>删除</MenuItem>
          </Menu>
        </>
      );
    },
  });
  return newCols;
};
关键修改说明
  • 用anchorEl存储触发菜单的按钮DOM元素,给Menu组件绑定该属性,保证菜单弹出位置正确
  • 新增activeRowId存储当前打开菜单的行ID,确保同一时间只有一个行的菜单处于打开状态
  • 每个菜单的ID和行ID绑定,避免DOM ID重复冲突
  • 操作列设置sortable和filterable为false,避免操作列出现排序/筛选按钮影响显示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 19:00:01