You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

react-pro-sidebar v1.0.0+react-router-dom v6.16.0:路由切换时保持SubMenu激活展开

侧边栏路由切换后保持SubMenu展开状态问题修复

问题背景

我使用react-pro-sidebar v1.0.0和react-router-dom v6.16.0创建了一个包含3个SubMenu及对应MenuItem的侧边栏。当前遇到的问题是:点击MenuItem切换路由后,所有SubMenu都会收起,用户无法清晰知晓当前所在页面,需要让用户点击的对应SubMenu保持激活并展开状态。

原代码

import { Link, useLocation } from "react-router-dom";
import { Sidebar, Menu, MenuItem, SubMenu } from "react-pro-sidebar";
import classes from "./MainLayout.module.css";
import { useEffect, useState } from "react";

export default function SidebarMenu() {
  const location = useLocation();
  const [openSubMenu, setOpenSubMenu] = useState(null);
  const [path, setPath] = useState(location.pathname);

  const routeMenuKeys = {
    "/users": "home",
    "/companies": "home",
    "/document-category": "document",
    "/document-type": "document",
    "/document-master": "document",
    "/file-category": "document",
    "/file-master": "document",
    "/file-location": "document",
    "/uploads": "document",
    "/task-category": "task",
    "/tasks": "task",
  };

  useEffect(() => {
    const currentRoute = path;
    const submenuKey = routeMenuKeys[currentRoute] || null;
    setOpenSubMenu(submenuKey);
  }, [path]);

  return (
    <>
      <Sidebar
        rootStyles={{
          minWidth: "100%",
          width: "100%",
          // backgroundColor: "transparent",
        }}
        className={classes.sidebar_dropmenu}
      >
        <Menu
          menuItemStyles={{
            button: {
              [`&:hover`]: {
                backgroundColor: "#d6d6d6",
              },
            },
          }}
        >
          <SubMenu label={`Home`}>
            <MenuItem
              component={<Link to="/" />}
              open={openSubMenu === "home"}
            >
              Dashboard
            </MenuItem>
            <MenuItem
              component={<Link to="/users" />}
              open={openSubMenu === "home"}
            >
              Users
            </MenuItem>
            <MenuItem
              component={<Link to="/companies" />}
              open={openSubMenu === "home"}
            >
              Companies
            </MenuItem>
          </SubMenu>
          <SubMenu label={`Document Management`}>
            <MenuItem
              component={<Link to="/document-category" />}
              open={openSubMenu === "document"}
            >
              Document Category
            </MenuItem>
            <MenuItem
              component={<Link to="/document-type" />}
              open={openSubMenu === "document"}
            >
              Document Type
            </MenuItem>
            <MenuItem
              component={<Link to="/document-master" />}
              open={openSubMenu === "document"}
            >
              Document Master
            </MenuItem>
            <MenuItem
              component={<Link to="/file-category" />}
              open={openSubMenu === "document"}
            >
              File Category
            </MenuItem>
            <MenuItem
              component={<Link to="/file-master" />}
              open={openSubMenu === "document"}
            >
              File Master
            </MenuItem>
            <MenuItem
              component={<Link to="/file-location" />}
              open={openSubMenu === "document"}
            >
              File Location
            </MenuItem>
            <MenuItem
              component={<Link to="/uploads" />}
              open={openSubMenu === "document"}
            >
              Uploads
            </MenuItem>
          </SubMenu>
          <SubMenu label={`Task Management`}>
            <MenuItem
              component={<Link to="/task-category" />}
              open={openSubMenu === "task"}
            >
              Task Category
            </MenuItem>
            <MenuItem
              component={<Link to="/tasks" />}
              open={openSubMenu === "task"}
            >
              Tasks
            </MenuItem>
          </SubMenu>
        </Menu>
      </Sidebar>
    </>
  );
}

修复方案

问题分析

  1. 未监听路由变化:原代码中path状态仅初始化一次,路由切换后不会自动更新,导致useEffect无法触发更新子菜单状态。
  2. open属性位置错误:将控制展开的open属性加在了MenuItem上,而非对应的SubMenu组件。
  3. 缺少根路径映射:根路径/未在routeMenuKeys中定义,导致Dashboard页面无法匹配到Home子菜单。

修改后的完整代码

import { Link, useLocation } from "react-router-dom";
import { Sidebar, Menu, MenuItem, SubMenu } from "react-pro-sidebar";
import classes from "./MainLayout.module.css";
import { useEffect, useState } from "react";

export default function SidebarMenu() {
  const location = useLocation();
  const [openSubMenu, setOpenSubMenu] = useState(null);

  // 补充根路径的映射
  const routeMenuKeys = {
    "/": "home",
    "/users": "home",
    "/companies": "home",
    "/document-category": "document",
    "/document-type": "document",
    "/document-master": "document",
    "/file-category": "document",
    "/file-master": "document",
    "/file-location": "document",
    "/uploads": "document",
    "/task-category": "task",
    "/tasks": "task",
  };

  // 监听location.pathname的变化,更新展开的子菜单
  useEffect(() => {
    const submenuKey = routeMenuKeys[location.pathname] || null;
    setOpenSubMenu(submenuKey);
  }, [location.pathname]);

  return (
    <>
      <Sidebar
        rootStyles={{
          minWidth: "100%",
          width: "100%",
          // backgroundColor: "transparent",
        }}
        className={classes.sidebar_dropmenu}
      >
        <Menu
          menuItemStyles={{
            button: {
              [`&:hover`]: {
                backgroundColor: "#d6d6d6",
              },
              // 可选:自定义激活菜单项样式
              [`&.active`]: {
                backgroundColor: "#b8b8b8",
              }
            },
          }}
        >
          {/* 将open属性移到SubMenu上 */}
          <SubMenu label={`Home`} open={openSubMenu === "home"}>
            <MenuItem
              component={<Link to="/" />}
              active={location.pathname === "/"}
            >
              Dashboard
            </MenuItem>
            <MenuItem
              component={<Link to="/users" />}
              active={location.pathname === "/users"}
            >
              Users
            </MenuItem>
            <MenuItem
              component={<Link to="/companies" />}
              active={location.pathname === "/companies"}
            >
              Companies
            </MenuItem>
          </SubMenu>
          <SubMenu label={`Document Management`} open={openSubMenu === "document"}>
            <MenuItem
              component={<Link to="/document-category" />}
              active={location.pathname === "/document-category"}
            >
              Document Category
            </MenuItem>
            <MenuItem
              component={<Link to="/document-type" />}
              active={location.pathname === "/document-type"}
            >
              Document Type
            </MenuItem>
            <MenuItem
              component={<Link to="/document-master" />}
              active={location.pathname === "/document-master"}
            >
              Document Master
            </MenuItem>
            <MenuItem
              component={<Link to="/file-category" />}
              active={location.pathname === "/file-category"}
            >
              File Category
            </MenuItem>
            <MenuItem
              component={<Link to="/file-master" />}
              active={location.pathname === "/file-master"}
            >
              File Master
            </MenuItem>
            <MenuItem
              component={<Link to="/file-location" />}
              active={location.pathname === "/file-location"}
            >
              File Location
            </MenuItem>
            <MenuItem
              component={<Link to="/uploads" />}
              active={location.pathname === "/uploads"}
            >
              Uploads
            </MenuItem>
          </SubMenu>
          <SubMenu label={`Task Management`} open={openSubMenu === "task"}>
            <MenuItem
              component={<Link to="/task-category" />}
              active={location.pathname === "/task-category"}
            >
              Task Category
            </MenuItem>
            <MenuItem
              component={<Link to="/tasks" />}
              active={location.pathname === "/tasks"}
            >
              Tasks
            </MenuItem>
          </SubMenu>
        </Menu>
      </Sidebar>
    </>
  );
}

关键修改点

  1. 监听路由变化:移除多余的path状态,直接监听location.pathname的变化,确保路由切换时能实时更新子菜单状态。
  2. 调整open属性位置:将open属性从MenuItem移到对应的SubMenu组件,控制子菜单的展开/收起。
  3. 补充根路径映射:在routeMenuKeys中添加"/": "home",让Dashboard页面能匹配到Home子菜单。
  4. 添加激活状态标记:给每个MenuItem添加active属性,根据当前路由判断是否激活,提升用户体验。

内容的提问来源于stack exchange,提问作者Reacting

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 17:28:12