The Problem
I have a sidebar with menus and some of the menus has submenus. I would like to close any opened menu with submenus when a different menu is clicked.
Stack
Written in React with react hooks
Sidebar
const [open, setOpen] = useState(true);
return (
<div>
<ul>
{SidebarData.map((item, index) => {
return (
<SubMenu
item={item}
key={index}
titleOpen={!open}
dropOpen={open}
subMenuOpen={open}
/>
);
})}
</ul>
</div>
);
}
SubMenu
function SubMenu({ item, titleOpen, dropOpen, subMenuOpen }) {
const [subnav, setSubnav] = useState(false);
const showSubnav = () => setSubnav(!subnav);
return (
<div>
<ul>
<Link to={item.path} onClick={item.subNav && showSubnav}>
<li>
<span>{item.icon}</span>
<span>
{item.title}
</span>
{item.subNav && dropOpen && (
<KeyboardArrowDownIcon/>
)}
</li>
</Link>
{subnav &&
subMenuOpen &&
item.subNav.map((item, index) => {
return (
<ul>
<Link to={item.path} key={index}>
<li>
<div>{item.title}</div>
</li>
</Link>
</ul>
);
})}
</ul>
</div>
);
}
Each menu has a unique id
CodePudding user response:
To achieve this you would need to move state of opened menus outside of the Submenu component and consume it as a prop instead.
Sidebar
const [openedMenuIndex, setOpenedMenuIndex] = useState(0);
return (
<div>
<ul>
{SidebarData.map((item, index) => (
<SubMenu
item={item}
key={index}
isOpened={openedMenuIndex === index}
onClickSubnav={() => setOpenedMenuIndex(index)}
/>
)}
</ul>
</div>
);
}
Submenu
function SubMenu({ item, isOpened, onClickSubnav}) {
return (
<div>
<ul>
<Link to={item.path} onClick={item.subNav && onClickSubnav}>
....
// later in the code show/hide subnav based on value in isOpened property
CodePudding user response:
There are probably a couple ways to do it, but I think the easiest would be to have a useState to keep track of the menu item that is expanded:
const [expanded, setExpanded] = React.useState("name of default menu item to expand"); // or React.useState(null) to collapse all by default
and then use that variable when determining whether or not to show something (and how you do it is up to you), e.g.:
<SubMenuItem visible={expanded === 'subitem3'} onChange={setExpanded('subitem3')}>
visible
is probably not a real property, but whatever it is that you use as the condition to determine whether the subitem is in an expanded state or not. Changing expanded
then re-evaluates all the other submenu item conditions, which will collapse them.