'How do I make sidebar automatically disappear once a menu item clicked
I implemented a some Sidebar code and would like the sidebar to automatically close once an item is clicked. Currently have to click the 'X' to hide sidebar. Below is the existing code for the Sidebar and Sidebar sub-menu.
Probably a one line fix if you know what you are doing, but I am new to React, so any help would be appreciated.
...
import React, { useState } from 'react';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import * as FaIcons from 'react-icons/fa';
import * as AiIcons from 'react-icons/ai';
import { SidebarData } from './SidebarData';
import SubMenu from './SubMenu';
import { IconContext } from 'react-icons/lib';
const Nav = styled.div`
// background: #15171c;
background: black;
height: 60px;
display: flex;
justify-content: flex-start;
align-items: center;
`;
const NavIcon = styled(Link)`
margin-left: 2rem;
font-size: 2rem;
height: 60px;
display: flex;
justify-content: flex-start;
align-items: center;
`;
// background: #15171c;
const SidebarNav = styled.nav`
background: #15171c;
width: 250px;
height: 150vh;
display: flex;
justify-content: center;
position: fixed;
top: 0;
left: ${({ sidebar }) => (sidebar ? '0' : '-100%')};
transition: 350ms;
z-index: 10;
`;
const SidebarWrap = styled.div`
width: 100%;
`;
const Sidebar = () => {
const [sidebar, setSidebar] = useState(false);
const showSidebar = () => setSidebar(!sidebar);
return (
<>
<IconContext.Provider value={{ color: '#fff' }}>
<Nav>
<NavIcon to='#'>
<FaIcons.FaBars onClick={showSidebar} />
</NavIcon>
</Nav>
<SidebarNav sidebar={sidebar}>
<SidebarWrap>
<NavIcon to='#'>
<AiIcons.AiOutlineClose onClick={showSidebar} />
</NavIcon>
{SidebarData.map((item, index) => {
return <SubMenu item={item} key={index} />;
})}
</SidebarWrap>
</SidebarNav>
</IconContext.Provider>
</>
);
};
export default Sidebar;
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import styled from 'styled-components';
const SidebarLink = styled(Link)`
display: flex;
color: #e1e9fc;
justify-content: space-between;
align-items: center;
padding: 20px;
list-style: none;
height: 40px;
text-decoration: none;
font-size: 18px;
//#c6c8cf
//#252831
&:hover {
background: #c6c8cf;
border-left: 4px solid #632ce4;
cursor: pointer;
}
`;
const SidebarLabel = styled.span`
margin-left: 16px;
`;
const DropdownLink = styled(Link)`
background: #414757;
height: 40px;
padding-left: 3rem;
display: flex;
align-items: center;
text-decoration: none;
color: #f5f5f5;
font-size: 18px;
// background: #632ce4;
&:hover {
background: #d9dbd5;
cursor: pointer;
}
`;
const SubMenu = ({ item }) => {
const [subnav, setSubnav] = useState(false);
const showSubnav = () => setSubnav(!subnav);
return (
<>
<SidebarLink to={item.path} onClick={item.subNav && showSubnav}>
<div>
{item.icon}
<SidebarLabel>{item.title}</SidebarLabel>
</div>
<div>
{item.subNav && subnav
? item.iconOpened
: item.subNav
? item.iconClosed
: null}
</div>
</SidebarLink>
{subnav &&
item.subNav.map((item, index) => {
return (
<DropdownLink to={item.path} key={index}>
{item.icon}
<SidebarLabel>{item.title}</SidebarLabel>
</DropdownLink>
);
})}
</>
);
};
export default SubMenu;
import React from 'react';
// import * as FaIcons from 'react-icons/fa';
import * as AiIcons from 'react-icons/ai';
import * as IoIcons from 'react-icons/io';
import * as RiIcons from 'react-icons/ri';
import * as FaIcons from 'react-icons/fa';
export const SidebarData = [
{
title: 'Login',
path: '/login',
icon: <AiIcons.AiOutlineLogin />,
},
{
title: 'Site Master',
path: '/list-sitemaster',
icon: <FaIcons.FaBroadcastTower />,
},
{
title: 'Site Report Cards',
path: '/sitereportcardmaster',
icon: <IoIcons.IoIosPaper />,
},
{
title: 'Report Card Master',
path: '/reportcardmaster',
icon: <IoIcons.IoIosPaper />
},
{
title: 'Categories',
path: '/categories',
icon: <IoIcons.IoIosClipboard />,
iconClosed: <RiIcons.RiArrowDownSFill />,
iconOpened: <RiIcons.RiArrowUpSFill />,
subNav: [
{
title: 'Asset Type',
path: '/assettype',
icon: <IoIcons.IoIosPaper />,
cName: 'sub-nav'
},
{
title: 'Asset Sub Type',
path: '/assetsubtype',
icon: <IoIcons.IoIosPaper />,
cName: 'sub-nav'
},
{
title: 'Document Type',
path: '/documenttype',
icon: <IoIcons.IoIosPaper />,
cName: 'sub-nav'
},
{
title: 'Document Sub Type',
path: '/documentsubtype',
icon: <IoIcons.IoIosPaper />,
cName: 'sub-nav'
},
{
title: 'Report Card Category',
path: '/reportcarddetailcategory',
icon: <IoIcons.IoIosPaper />,
cName: 'sub-nav'
},
{
title: 'Contact Detail Type',
path: '/contactdetailtype',
icon: <IoIcons.IoIosPaper />,
cName: 'sub-nav'
},
{
title: 'Lighting Type',
path: '/lightingtype',
icon: <IoIcons.IoIosPaper />,
cName: 'sub-nav'
}
]
},
{
title: 'Company Master',
path: '/cpymaster-toplevel',
icon: <AiIcons.AiFillHome />,
iconClosed: <RiIcons.RiArrowDownSFill />,
iconOpened: <RiIcons.RiArrowUpSFill />,
subNav: [
{
title: 'CompanyMaster',
path: '/cpymaster',
icon: <AiIcons.AiFillHome />,
cName: 'sub-nav'
},
{
title: 'Users',
path: '/users',
icon: <IoIcons.IoIosPerson />,
cName: 'sub-nav'
},
{
title: 'Contacts',
path: '/contactmaster',
icon: <IoIcons.IoIosPeople />,
cName: 'sub-nav'
}
]
},
{
title: 'My Profile',
path: '/add-usersmall',
icon: <AiIcons.AiOutlineUser/>,
},
{
title: 'PDF',
path: '/pdfcomponent',
icon: <AiIcons.AiOutlineUser/>,
},
{
title: 'Users PageSort Test',
path: '/userstable',
icon: <AiIcons.AiOutlineUser/>,
},
{
title: 'Logout',
path: '/logout',
icon: <AiIcons.AiOutlineLogin />,
}
];
...
Solution 1:[1]
You have a state for the sidebar in
const Sidebar = () => {
const [sidebar, setSidebar] = useState(false);
const showSidebar = () => setSidebar(!sidebar);
...
If I'm not wrong, you close it in
<AiIcons.AiOutlineClose onClick={showSidebar} />
You can pass down that showSidebar function to the link components, somthing like
<SubMenu item={item} key={index} toggleSidebar={showSidebar}/>
(Also, avoid using index as key) Receiving the funtion in the SubMenu component
const SubMenu = ({ item,toggleSidebar }) => {
thus, you are able to use it in the link
Solution 2:[2]
The following code in the subMenu.js along with @Daniel toggleSidebar code in sideBar.js rendered the desired results.
...
return (
<>
<SidebarLink to={item.path} onClick={item.subNav && showSubnav}>
<div>
{item.icon}
{/*following onClick={toggleSidebar} allows mainm menu items without subnav to close sidebar */}
<SidebarLabel onClick={toggleSidebar}>{item.title}</SidebarLabel>
</div>
<div>
{item.subNav && subnav
? item.iconOpened
: item.subNav
? item.iconClosed
: null}
</div>
</SidebarLink>
{subnav &&
item.subNav.map((item, index) => {
return (
//following onClick={toggleSidebar} allows submenu selections to close sidebar
<DropdownLink to={item.path} key={index} onClick={toggleSidebar}>
{item.icon}
<SidebarLabel>{item.title}</SidebarLabel>
</DropdownLink>
);
})}
</>
);
...
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | daniel |
| Solution 2 | HighwayRob |

