I have this code for a sidebar, it has to render the 3 sections, "laboratorio"
, "sucursales"
and "recursos humanos"
, the submenu of each one is taken from the sseccion
of each const. However, I don’t know how to render the 3 and that each one has independent operation, since now the 3 menus are opened at the same time and are displayed multiple times.
import React, { useState } from 'react';
import { SideBarWrapper, Arrow } from './Sidebar.styles';
const Sidebar: React.FC = () => {
const [isExpanded, setIsExpanded] = useState<boolean>(false);
const toggleExpand = () => {
setIsExpanded(!isExpanded);
};
const permisos = [
{
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 },
],
},
];
const BarContainer = (object: any) => {
const lab = {
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 },
],
};
const sucursales = {
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 },
],
};
const recursoshumanos = {
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>
<div className="menu-item" onClick={toggleExpand}>
<div className="menu-title">{lab.smodulo}</div>
<Arrow isExpanded={isExpanded} />
</div>
{isExpanded && (
<div className="submenu">
{lab.secciones.map((seccion: any, index: number) => (
<div className="submenu-item" key={index}>
{seccion.sseccion}
</div>
))}
</div>
)}
<div className="menu-item" onClick={toggleExpand}>
<div className="menu-title">{sucursales.smodulo}</div>
<Arrow isExpanded={isExpanded} />
</div>
{isExpanded && (
<div className="submenu">
{sucursales.secciones.map((seccion: any, index: number) => (
<div className="submenu-item" key={index}>
{seccion.sseccion}
</div>
))}
</div>
)}
<div className="menu-item" onClick={toggleExpand}>
<div className="menu-title">{recursoshumanos.smodulo}</div>
<Arrow isExpanded={isExpanded} />
</div>
{isExpanded && (
<div className="submenu">
{recursoshumanos.secciones.map((seccion: any, index: number) => (
<div className="submenu-item" key={index}>
{seccion.sseccion}
</div>
))}
</div>
)}
</SideBarWrapper>
);
};
return (
<>
{permisos.map((permiso, index) => (
<BarContainer key={index} lab={permiso} />
))}
</>
);
};
export default Sidebar;
The objective is to render the 3 sections, taking the data from the submenu of each of the const, which are dynamic. And that each one has independent operation, that each one can be opened and closed without affecting the other two.
2
Answers
I understand your goal. Let’s modify the code to render the three sections independently, each with its own state for expansion. Here’s the revised version of your Sidebar component:
Here’s what I’ve changed:
I’ve combined all the modules (Laboratorio, Sucursales, Recursos Humanos) into a single array called
modules
. This makes it easier to render them dynamically.Instead of a single
isExpanded
state, I’ve created anexpandedModules
object state. This object keeps track of the expanded state for each module independently.The
toggleExpand
function now takes a module name as an argument and toggles the state for that specific module.In the render method, I’m mapping over the
modules
array to create each section of the sidebar.Each section now has its own onClick handler that calls
toggleExpand
with the module name.The Arrow component and the submenu rendering now depend on the expanded state of each individual module.
This implementation allows each section to be opened and closed independently, and the submenus are populated dynamically from the
secciones
array of each module.Issue
You have used only a single boolean state that controls all the menus you want to toggle open/close.
All menu sections get toggled together at the same time.
Solution
Update the state to hold an object of boolean values to independently toggle specific sections.
Update the
isExpanded
state from a singleboolean
value to a map/look objectRecord<string, boolean>
.Update the
toggleExpand
handler to consume a unique section identifier so just that section’s expanded state can be toggled. Thesmodulo
property seems to be a good candidate.Check for what is expanded using
isExpanded[section.smodulo]
.Move the static
permisos
data out of theSidebar
component.Don’t declare React components within other React components, so remove the nested
BarContainer
component declaration.Make the code more DRY (Don’t Repeat Yourself) by mapping the
permisos
array of the sections to JSX, then map each section’ssecciones
array of items.Avoid using array indices as React keys, use a unique property value intrinsic to the data, e.g.
section.smodulo
for the sections andseccion.sseccion
for the items.Example: