Material-UI 的 Menu 菜单点击后不关闭怎么办?

Des.玉飞 阅读 35

我用 Material-UI 写了个下拉菜单,点击菜单项之后菜单不会自动关闭,得点外面才行,这体验太差了。

我试过在 MenuItem 的 onClick 里手动调用 setAnchorEl(null),但有时候还是关不掉,特别是用了 React.memo 包裹组件之后。是不是哪里漏了?

const handleClick = (event) => {
  setAnchorEl(event.currentTarget);
};

const handleClose = () => {
  setAnchorEl(null);
};

return (
  <>
    <Button onClick={handleClick}>打开菜单</Button>
    <Menu anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleClose}>
      <MenuItem onClick={handleClose}>选项1</MenuItem>
      <MenuItem onClick={handleClose}>选项2</MenuItem>
    </Menu>
  </>
);
我来解答 赞 13 收藏
二维码
手机扫码查看
2 条解答
雨萓 Dev
这个问题挺常见的,根本原因是你在 MenuItem 上手动加了 onClick 跟 Menu 的 onClose 抢关闭逻辑,容易产生竞态。

Material-UI 的 Menu 组件其实自带关闭逻辑,你不需要在每个 MenuItem 上写 onClick 关它。Menu 内部会捕获 MenuItem 的点击事件然后触发 onClose。

改成这样就行:

<Menu anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleClose}>
<MenuItem onClick={handleMenuItemClick}>选项1</MenuItem>
<MenuItem onClick={handleMenuItemClick}>选项2</MenuItem>
</Menu>


然后你的业务逻辑放在 handleMenuItemClick 里执行,执行完了再调 handleClose:

const handleMenuItemClick = (event) => {
// 在这里处理你的业务逻辑
doSomething();
// 最后关闭菜单
handleClose();
};


如果你用了 React.memo 之后出问题,大概率是闭包捕获了旧状态。解决办法是确保 handleClose 是用 useCallback 包的,并且依赖项写对:

const handleClose = useCallback(() => {
setAnchorEl(null);
}, []);


或者更干脆——别在 MenuItem 上绑 onClick,就让 Menu 自己处理关闭,你需要做的只是监听菜单关闭后的事件。
点赞 1
2026-03-11 15:12
西门莉娜
你这问题我遇到过,Material-UI的Menu确实有点小坑。关键点在于你需要在点击MenuItem后同时触发handleClose和MenuItem自己的点击逻辑。

试试这个优化方案:

const handleItemClick = (callback) => () => {
handleClose();
callback?.();
};

// 使用例子
<Menu anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleClose}>
<MenuItem onClick={handleItemClick(() => console.log('选项1被点击'))}>
选项1
</MenuItem>
</Menu>


这样改有几个好处:
1. 把关闭逻辑和业务逻辑解耦了
2. 确保每次点击都会先关闭菜单
3. 不会因为React.memo之类的优化导致关闭失效

如果MenuItem有独立的点击处理逻辑,就把逻辑函数传给handleItemClick。我用这招解决了不少莫名其妙的菜单关闭问题,MUI的组件有时候确实需要点workaround。
点赞
2026-03-08 23:00