1

I am building a react admin panel with a sidebar and when the link inside the sidebar is clicked it should render the component which is being clicked and the component is not rendering properly. I looked at the previous submissions by other developers and they were using react-router v5 and the current version is v6.

This is the following code I have tried and it's not working accordingly.

app.jsx

function App() {
  return (
    <>
      <BrowserRouter>
        <Header />
        <Routes>
          <Route path="/" index element={<Home />} />
          <Route path="/login" element={<Login />} />
          <Route path="/adminPanel" element={<AdminPanel />} />
          <Route path="/dashboard" element={<Dashboard />} />
          <Route path="/scanNow" element={<ScanNow />} />
          <Route path="/scanHistory" element={<ScanHistory />} />
          <Route path="/users" element={<Users />} />
          <Route path="/profile" element={<Profile />} />
          <Route path="/settings" element={<Settings />} />
        </Routes>
      </BrowserRouter>
    </>
  )
}

export default App

adminPanel

export default function AdminPanel() {
  const [selectedComponent, setSelectedComponent] = useState("");

  const location = useLocation();
  // const isLoggedIn = location.pathname.includes('adminPanel');

  return (
    <>
      <div className="adminPanel">
        <div className="adminPanel__container">
          <SideBar />
          <div>
            {selectedComponent === 'dashboard' && <Dashboard />}
            {selectedComponent === 'scanNow' && <ScanNow />}
            {selectedComponent === 'scanHistory' && <ScanHistory />}
            {selectedComponent === 'users' && <Users />}
            {selectedComponent === 'profile' && <Profile />}
            {selectedComponent === 'settings' && <Settings />}
          </div>
        </div>
      </div>
    </>
  )
}

sidebar.jsx

export default function SideBar() {
  const [showMobSidebar, setShowMobSidebar] = useState(false);
  const [activeLink, setActiveLink] = useState("");

  // useEffect to show the mobile sidebar when the component mounts and event
  // listener is added and removed
  useEffect(() => {
    setShowMobSidebar(window.innerWidth < 767);

    const handleResize = () => {
      setShowMobSidebar(window.innerWidth < 767);
    };

    window.addEventListener("resize", handleResize);

    return () => {
      window.removeEventListener("resize", handleResize);
    };
  }, []);

  // handle the click for the active link
  const handleLinkClick = (link) => {
    setActiveLink(link);
  };

  return (
    <>
      {showMobSidebar ? (
        <MobileSidebar />
      ) : (
        <div className="sidebar">
          <ul className="sidebar__lists">
            <li className="sidebar__lists-item">
              <Link
                className={`sidebar__lists-link ${activeLink === "dashboard" ? "active" : ""}`}
                to="/dashboard"
                onClick={() => handleLinkClick("dashboard")}
              >
                <MdDashboard className="react-icons" />
                Dashboard
              </Link>
            </li>
            <li className="sidebar__lists-item">
              <Link
                className={`sidebar__lists-link ${activeLink === "scanNow" ? "active" : ""}`}
                to="/scanNow"
                onClick={() => handleLinkClick("scanNow")}
              >
                <CgPhotoscan className="react-icons" />
                Scan Now
              </Link>
            </li>
            <li className="sidebar__lists-item">
              <Link
                className={`sidebar__lists-link ${activeLink === "scanHistory" ? "active" : ""}`}
                to="/scanHistory"
                onClick={() => handleLinkClick("scanHistory")}
              >
                <MdHistory className="react-icons" />
                Scan History
              </Link>
            </li>
            <li className="sidebar__lists-item">
              <Link
                className={`sidebar__lists-link ${activeLink === "users" ? "active" : ""}`}
                to="/users"
                onClick={() => handleLinkClick("users")}
              >
                <HiOutlineUsers className="react-icons" />
                Users
              </Link>
            </li>
            <li className="sidebar__lists-item">
              <Link
                className={`sidebar__lists-link ${activeLink === "profile" ? "active" : ""}`}
                to="/profile"
                onClick={() => handleLinkClick("profile")}
              >
                <CgProfile className="react-icons" />
                Profile
              </Link>
            </li>
            <li className="sidebar__lists-item">
              <Link
                className={`sidebar__lists-link ${activeLink === "settings" ? "active" : ""}`}
                to="/settings"
                onClick={() => handleLinkClick("settings")}
              >
                <MdOutlineSettings className="react-icons" />
                Settings
              </Link>
            </li>
            <li className="sidebar__lists-item">
              <Link
                className={`sidebar__lists-link ${activeLink === "logout" ? "active" : ""}`}
                to="/login"
                onClick={() => handleLinkClick("logout")}
              >
                <MdOutlineLogout className="react-icons" />
                Logout
              </Link>
            </li>
          </ul>
        </div>
      )}
    </>
  );
}

`

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • You should also use the `NavLink` component instead of the `Link` component, it gets the active "state" basically for free. No need to reinvent the wheel. – Drew Reese Feb 10 '23 at 00:57
  • Thank you for your advice. NavLink active state cut down on a big chunk of code. I do have another question regarding the setup of the paths for the Home component and the AdminPanel component using . The Home component is the homepage and its default path is "/". I'm trying to set the path for the AdminPanel component and its child elements, but I'm not sure how to do it correctly. – user19662721 Feb 10 '23 at 02:48
  • The `AdminPanel` has no children routes/elements. Are you saying you want something like `"/adminPanel/dashboard"`, `"/adminPanel/scanNow"`, etc? – Drew Reese Feb 10 '23 at 02:51
  • Yes exactly that "/adminPanel/dashboard" – user19662721 Feb 10 '23 at 02:59
  • You've basically also reinvented the route matching wheel that `Routes` handles with the logic in `AdminPanel` that uses the `location` object. Convert `AdminPanel` into a [Layout Route](https://reactrouter.com/en/main/start/concepts#layout-routes) component that renders an `Outlet` instead of the `selectedComponent` stuff (*which can be completely removed, BTW*) and nest the other routes in the new `AdminPanel` layout route. The nested routes will have paths relative to the `"/adminPanel"` parent route path. Does this make sense? – Drew Reese Feb 10 '23 at 03:03

0 Answers0