如何使用多map函数创建Material UI嵌套列表侧边栏
React + MUI 嵌套侧边栏列表解决方案
问题回顾
在React应用中使用MUI构建带嵌套项的侧边栏时,需实现当accountType为Group时,展开显示其下providers子列表的功能,但在数据映射环节遇到问题。
示例数据
const sidebarData = [ { id: 1, accountType: "Individual", name: "John Doe", icon: <PersonIcon /> }, { id: 2, accountType: "Group", name: "Team Alpha", icon: <GroupIcon />, providers: [ { id: 21, name: "Provider A", icon: <BusinessIcon /> }, { id: 22, name: "Provider B", icon: <BusinessIcon /> } ] }, { id: 3, accountType: "Individual", name: "Jane Smith", icon: <PersonIcon /> } ];
修复后的完整代码
import React from 'react'; import { List, ListItem, ListItemIcon, ListItemText, Collapse } from '@mui/material'; import { PersonIcon, GroupIcon, BusinessIcon, ExpandLess, ExpandMore } from '@mui/icons-material'; const sidebarData = [ // 上述示例数据 ]; const Sidebar = () => { // 存储每个Group项的展开状态,初始为空对象(默认全部折叠) const [openGroups, setOpenGroups] = React.useState({}); // 切换指定Group的展开/折叠状态 const toggleGroup = (groupId) => { setOpenGroups(prev => ({ ...prev, [groupId]: !prev[groupId] })); }; return ( <List> {sidebarData.map(item => ( <React.Fragment key={item.id}> {/* 父列表项 */} <ListItem button onClick={() => item.accountType === 'Group' && toggleGroup(item.id)} > <ListItemIcon>{item.icon}</ListItemIcon> <ListItemText primary={item.name} /> {/* 仅Group项显示展开/折叠图标 */} {item.accountType === 'Group' && ( openGroups[item.id] ? <ExpandLess /> : <ExpandMore /> )} </ListItem> {/* 嵌套子列表:仅Group项且存在providers时渲染 */} {item.accountType === 'Group' && item.providers?.length && ( <Collapse in={openGroups[item.id]} timeout="auto" unmountOnExit> <List component="div" disablePadding> {item.providers.map(provider => ( <ListItem key={provider.id} button sx={{ paddingLeft: 4 }} // 缩进子项,强化嵌套层级 > <ListItemIcon>{provider.icon}</ListItemIcon> <ListItemText primary={provider.name} /> </ListItem> ))} </List> </Collapse> )} </React.Fragment> ))} </List> ); }; export default Sidebar;
核心优化说明
- 状态管理:使用对象
openGroups存储每个Group的展开状态,解决多个Group项无法独立控制展开/折叠的问题 - 子项映射:在
Collapse组件内部通过item.providers.map()遍历生成子列表,同时用sx样式添加缩进,符合嵌套视觉逻辑 - 边界处理:通过
item.providers?.length判断,避免providers为空或未定义时渲染无效内容 - 交互优化:仅给Group类型的列表项绑定折叠切换事件,避免无意义的状态更新
内容的提问来源于stack exchange,提问作者Faslu Rahman Kadavath
相关产品推荐
相关产品推荐

