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

React侧边栏多模块独立展开折叠问题及代码优化需求

解决React侧边栏菜单同步展开/折叠与重复渲染问题

问题根源

  • 同步展开/折叠:使用单个isExpanded布尔状态控制所有模块,所有菜单共享同一状态
  • 重复渲染:遍历permisos数组渲染BarContainer,但BarContainer内部硬编码了三个模块,导致每个permisos项都渲染一遍完整菜单,最终重复三次

修复后的代码

import React, { useState } from 'react';
import { SideBarWrapper, Arrow } from './Sidebar.styles';

// 定义类型提升代码健壮性
type Seccion = {
  kms: number;
  sseccion: string;
  bedicion: boolean;
};

type Modulo = {
  kmodulo: number;
  smodulo: string;
  secciones: Seccion[];
};

const Sidebar: React.FC = () => {
  // 用对象存储每个模块的展开状态,初始全部折叠
  const [expandedModules, setExpandedModules] = useState<Record<string, boolean>>({
    'Laboratorio': false,
    'Sucursales': false,
    'Recursos Humanos': false
  });

  // 单个模块的展开/折叠切换函数,接收模块名称作为参数
  const toggleModule = (moduleName: string) => {
    setExpandedModules(prev => ({
      ...prev,
      [moduleName]: !prev[moduleName]
    }));
  };

  const permisos: Modulo[] = [
    {
      kmodulo: 3,
      smodulo: 'Laboratorio',
      secciones: [
        { kms: 10, sseccion: 'Atención a clientes', bedicion: true },
        { kms: 15, sseccion: 'Caja', bedicion: true },
        { kms: 14, sseccion: 'Paciente 360', bedicion: true },
      ],
    },
    {
      kmodulo: 3,
      smodulo: 'Sucursales',
      secciones: [
        { kms: 10, sseccion: 'Caja - Cobro', bedicion: true },
        { kms: 15, sseccion: 'Clientes', bedicion: true },
        { kms: 14, sseccion: 'Convenios', bedicion: true },
        { kms: 13, sseccion: 'Listas de Precio', bedicion: true },
        { kms: 11, sseccion: 'Médicos', bedicion: true },
        { kms: 12, sseccion: 'Pacientes', bedicion: true },
      ],
    },
    {
      kmodulo: 3,
      smodulo: 'Recursos Humanos',
      secciones: [
        { kms: 10, sseccion: 'Caja - Cobro', bedicion: true },
        { kms: 15, sseccion: 'Clientes', bedicion: true },
        { kms: 14, sseccion: 'Convenios', bedicion: true },
        { kms: 13, sseccion: 'Listas de Precio', bedicion: true },
        { kms: 11, sseccion: 'Médicos', bedicion: true },
        { kms: 12, sseccion: 'Pacientes', bedicion: true },
      ],
    },
  ];

  return (
    <SideBarWrapper>
      {/* 直接遍历permisos数组渲染每个模块,避免重复 */}
      {permisos.map((modulo) => (
        <div key={modulo.smodulo}>
          <div className="menu-item" onClick={() => toggleModule(modulo.smodulo)}>
            <div className="menu-title">{modulo.smodulo}</div>
            {/* 根据当前模块的展开状态渲染箭头 */}
            <Arrow isExpanded={expandedModules[modulo.smodulo]} />
          </div>
          {/* 仅当当前模块展开时渲染子菜单 */}
          {expandedModules[modulo.smodulo] && (
            <div className="submenu">
              {modulo.secciones.map((seccion) => (
                <div className="submenu-item" key={seccion.kms}>
                  {seccion.sseccion}
                </div>
              ))}
            </div>
          )}
        </div>
      ))}
    </SideBarWrapper>
  );
};

export default Sidebar;

关键改动说明

  • 独立控制展开状态:将单个布尔状态isExpanded改为对象expandedModules,以模块名称为键存储每个模块的展开状态,确保每个模块的展开/折叠操作互不影响
  • 消除重复渲染:移除BarContainer组件及内部硬编码的模块数据,直接遍历permisos数组渲染每个模块,避免重复渲染三次完整菜单
  • 类型定义优化:添加Seccion和Modulo类型,替代any类型,提升代码可读性和健壮性
  • 子菜单key优化:使用seccion.kms作为子菜单的key,比索引更稳定,符合React最佳实践

内容的提问来源于stack exchange,提问作者Diego Murillo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 03:00:53