React TypeScript+Material UI 子菜单未按分类渲染重叠如何解决
React + TypeScript + Material UI 菜单堆叠渲染异常修复
问题描述
开发菜单功能时出现渲染异常:所有子菜单未归属到对应正确的父级分类菜单下,全部堆叠重叠渲染,无法按所属分类独立展示。
预期效果
- 消息菜单(Message Menu)仅渲染对应的Menu List下拉菜单
- 操作菜单(Operation Menu)仅渲染Ack、Unack、Clear、Comment四个菜单项
问题根因
现有代码存在两个核心逻辑漏洞:
- 所有父菜单共用同一个
anchorEl和开关状态,点击任意父菜单都会触发同一个Menu弹出层渲染 - 子菜单渲染时未做父级关联过滤,直接全量遍历所有子菜单项塞进同一个弹出层,导致内容堆叠
修复步骤
1. 重构状态管理
废弃原来单一的open布尔状态,改为同时存储弹出层锚点元素、当前激活的父菜单唯一标识,区分不同父菜单的触发状态:
// 替换原有的open、setAnchorEl相关状态 const [activeMenu, setActiveMenu] = useState<{ anchorEl: HTMLElement | null; parentKey: string | number | null; // 存储当前打开的父菜单唯一标识 }>({ anchorEl: null, parentKey: null }); // 点击父菜单时传入当前菜单的唯一标识 const handleOpenMenu = (parentKey: string | number, event: React.MouseEvent<HTMLButtonElement>) => { setActiveMenu({ anchorEl: event.currentTarget, parentKey: parentKey }); }; const handleCloseMenu = () => { setActiveMenu({ anchorEl: null, parentKey: null }); };
2. 绑定父菜单触发事件
每个父菜单触发按钮点击时,传入自身对应的唯一标识,比如消息菜单传message、操作菜单传operation:
{/* 消息菜单触发按钮 */} <Button id="message-menu-btn" onClick={(e) => handleOpenMenu('message', e)} > 消息菜单 </Button> {/* 操作菜单触发按钮 */} <Button id="operation-menu-btn" onClick={(e) => handleOpenMenu('operation', e)} > 操作菜单 </Button>
3. 过滤渲染对应子菜单
Menu组件渲染子项时,先根据当前激活的父菜单标识过滤匹配的子项,再遍历渲染,不要全量输出所有子菜单:
<Menu id="common-pop-menu" anchorEl={activeMenu.anchorEl} open={!!activeMenu.anchorEl} onClose={handleCloseMenu} MenuListProps={{ "aria-labelledby": activeMenu.parentKey === 'message' ? 'message-menu-btn' : 'operation-menu-btn', }} > {/* 按父级标识过滤子项,字段名根据实际业务数据结构替换 */} {customtoolinfo.menu_sub .filter(subItem => subItem.parent_flag === activeMenu.parentKey) .map((subItem) => ( <MenuItem key={subItem.id} onClick={handleCloseMenu}> {subItem.menu_sub_name} </MenuItem> ))} </Menu>
如果你的菜单数据是嵌套结构(父菜单通过
children字段挂载对应子项),不需要做filter过滤,直接取当前激活父菜单的children数组遍历即可。
内容的提问来源于stack exchange,提问作者Seth
相关产品推荐
相关产品推荐

