为什么调用setAnchorEl(null)无法更新状态关闭Material UI的Menu组件?
问题根因
你的代码问题是事件冒泡导致状态更新被覆盖:
你将<Menu>组件直接嵌套在负责触发菜单打开的<MenuItem>内部,当你点击菜单内的选项、或者点击外部触发handleClose将anchorEl设为null后,点击事件会向上冒泡到父级<MenuItem>,触发handleProfileMenuOpen再次将anchorEl赋值为当前父<MenuItem>元素,相当于刚执行完关闭逻辑又立刻触发了打开逻辑,所以看起来setAnchorEl(null)没有生效,useEffect自然也监听不到anchorEl的变化。
修复方案
调整DOM结构,将<Menu>从触发打开的<MenuItem>内部移出即可,修复后的完整代码如下:
const {useState, useEffect} = React; const { ClickAwayListener, Menu, MenuItem, IconButton } = MaterialUI; function MenuAppBar(props) { const [anchorEl, setAnchorEl] = useState(null); const isProfileMenuOpen = Boolean(anchorEl); // For debugging purposes: useEffect(() => { console.log(anchorEl); }, [anchorEl]); const handleClose = () => { console.log("Closing menu"); setAnchorEl(null); }; const handleProfileMenuOpen = (event) => { setAnchorEl(event.currentTarget); } return ( <ClickAwayListener onClickAway={handleClose}> {/* 触发菜单的MenuItem内部不再嵌套Menu */} <MenuItem onClick={handleProfileMenuOpen}> <IconButton style={{ backgroundColor: "#F5B089" }} /> </MenuItem> {/* Menu移到外层 */} <Menu anchorEl={anchorEl} keepMounted open={isProfileMenuOpen} onClose={handleClose} > <MenuItem onClick={handleClose}>Profile</MenuItem> <MenuItem onClick={handleClose}>My account</MenuItem> <MenuItem>Logout</MenuItem> </Menu> </ClickAwayListener> ); } ReactDOM.render( <MenuAppBar />, document.getElementById("react") );
HTML部分无需修改:
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script> <script src="https://unpkg.com/@material-ui/core@latest/umd/material-ui.development.js"></script> <div id="react"></div>
内容的提问来源于stack exchange,提问作者Axel Köhler
相关产品推荐
相关产品推荐

