You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用多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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 03:46:12