In a dashboard layout, let’s say I have a sidebar that contains the option ‘Leave’. When I click on leave, leave gets highlighted on the sidebar, and the leave component is displayed. In the leave component, there is a button ‘Apply Leave’. When I click on ‘Apply Leave’, the Apply Leave Component containing the form is displayed, but ‘Leave’ on sidebar is not highlighted anymore.
Also I want to make the sidebar scroll independently of the browser scrolling and show the scrollbars only while scrolling. Just like youtube sidebar which scrolls seperately from the video feed scrollbar.
Here is my code:
Sidebar.js
import { useState, useEffect } from "react";
import { useLocation } from "react-router-dom";
import "../assets/styles/Sidebar.css";
import SidebarItem from "./SidebarItem";
function Sidebar() {
const location = useLocation();
const [selectedItem, setSelectedItem] = useState("");
useEffect(() => {
const pathname = location.pathname;
const item = getItemFromPathname(pathname);
setSelectedItem(item);
}, [location]);
const getItemFromPathname = (pathname) => {
const parts = pathname.split("/");
const lastPart = parts[parts.length - 1];
switch (lastPart) {
case "":
case "profile":
return "Profile";
case "calendar":
return "Calendar";
case "leave":
return "Leave";
default:
return "";
}
};
const handleItemClick = (title) => {
setSelectedItem(title);
};
return (
<section className="sidebar">
<SidebarItem
to="/"
title="Profile"
selected={selectedItem === "Profile"}
onClick={() => handleItemClick("Profile")}
/>
<SidebarItem
to="/calendar"
title="Calendar"
selected={selectedItem === "Calendar"}
onClick={() => handleItemClick("Calendar")}
/>
<SidebarItem
to="/leave"
title="Leave"
selected={selectedItem === "Leave"}
onClick={() => handleItemClick("Leave")}
/>
</section>
);
}
export default Sidebar;
SidebarItem.js
import { Link } from "react-router-dom";
import "../assets/styles/SidebarItem.css"
function SidebarItem(props) {
return (
<Link to={props.to} className="sidebar-item-link">
<div
className={`sidebar-item ${props.selected && "selected"}`}
onClick={props.onClick}
>
{props.title}
</div>
</Link>
);
}
export default SidebarItem;
SidebarItem.css
.sidebar-item.selected {
border-left: 10px solid #63809f;
font-weight: bold;
}
2
Answers
you can create a function to check if you are in the route (or subroute) of selected sidebar button.
maybe something like this:
then use it like this:
hope this helps
PS: if you are using JS instead of TS just remove types in function params
You might just need to switch over to using the
NavLink
component which includes route path matching functionality already, no need to re-invent the wheel.Example:
When the current URL path is
"/leave/*"
(or"/calendar/*"
, etc) the sidebar item will be active, or "selected".There’s likely also no need for the
selectedItem
state in the parent component now since selected/active state is computed byreact-router-dom
and theNavLink
component.* Note: The
end
prop is used specifically for"/"
so it’s not also matched with other sub-routes. The alternative here would be to give the Profile page its own non-"/" path, e.g."/profile"
.