Next.js中使用Material UI Collapse组件构建汉堡菜单报错求助
问题分析与修复方案
1. Collapse组件导入错误
你的代码里Collapse的导入方式完全错误:
import Collapse from "@mui/material";
MUI的组件需要从具体的组件路径导入,正确的导入应该是:
import Collapse from "@mui/material/Collapse";
直接导入@mui/material会拿到整个包的导出对象,而非Collapse组件本身,这是导致报错的核心原因。
2. 全局状态导致所有子菜单同步展开
当前用单个open状态控制所有带submenu的项,点击任何一个子菜单按钮,所有子菜单都会同时展开/收起。需要给每个子菜单单独维护状态,比如用对象记录每个菜单标题的展开状态:
const [openMenus, setOpenMenus] = useState({}); const handleClick = (title) => { setOpenMenus(prev => ({ ...prev, [title]: !prev[title] })); };
3. List组件嵌套结构错误
- 子菜单里
ListItemButton嵌套ListItem是冗余且错误的结构,MUI中ListItemButton本身就是可交互的列表项容器,直接在里面放置ListItemText即可。 - 非子菜单项里错误地把
ListItemText放在ListItemIcon内部,ListItemIcon是用来放图标的容器,文本应该和它同级放置。
修复后的完整代码
import * as React from "react"; import { useState } from "react"; import IconButton from "@mui/material/IconButton"; import ListSubheader from "@mui/material/ListSubheader"; import { Drawer } from "@mui/material"; import List from "@mui/material/List"; import ListItemButton from "@mui/material/ListItemButton"; import ListItemIcon from "@mui/material/ListItemIcon"; import ListItemText from "@mui/material/ListItemText"; import MenuIcon from "@mui/icons-material/Menu"; import { ExpandLess, ExpandMore } from "@mui/icons-material"; import Collapse from "@mui/material/Collapse"; const myMenu = [ { title: "about" }, { title: "services", submenu: [{ title: "Digital Marketing" }, { title: "Promotion" }], }, { title: "blog" }, { title: "contact" }, ]; const ResponsiveAppBar = () => { const [openDrawer, setOpenDrawer] = useState(false); // 用对象记录每个菜单的展开状态 const [openMenus, setOpenMenus] = useState({}); const handleClick = (title) => { setOpenMenus((prev) => ({ ...prev, [title]: !prev[title], })); }; return ( <React.Fragment> <Drawer anchor="right" open={openDrawer} onClose={() => setOpenDrawer(false)} > <List sx={{ width: "100%", maxWidth: 360, bgcolor: "background.paper" }} component="nav" aria-labelledby="nested-list-subheader" subheader={ <ListSubheader component="div" id="nested-list-subheader"> Navigation </ListSubheader> } > {myMenu.map((page, index) => page.submenu ? ( <div key={index}> <ListItemButton onClick={() => handleClick(page.title)}> <ListItemText primary={page.title} /> {openMenus[page.title] ? <ExpandLess /> : <ExpandMore />} </ListItemButton> <Collapse in={openMenus[page.title]} timeout="auto" unmountOnExit > <List component="div" disablePadding> {page.submenu.map((sub, subIndex) => ( <ListItemButton key={subIndex} sx={{ pl: 4 }}> <ListItemText primary={sub.title} /> </ListItemButton> ))} </List> </Collapse> </div> ) : ( <ListItemButton key={index}> {/* 这里可以添加对应图标,比如HomeIcon等 */} <ListItemIcon></ListItemIcon> <ListItemText primary={page.title} /> </ListItemButton> ) )} </List> </Drawer> <IconButton sx={{ color: "black", marginLeft: "auto" }} onClick={() => setOpenDrawer(!openDrawer)} > <MenuIcon color="white" /> </IconButton> </React.Fragment> ); }; export default ResponsiveAppBar;
内容的提问来源于stack exchange,提问作者Tabim
相关产品推荐
相关产品推荐

