react-pro-sidebar v1.0.0+react-router-dom v6.16.0:路由切换时保持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> </> ); }
修复方案
问题分析
- 未监听路由变化:原代码中
path状态仅初始化一次,路由切换后不会自动更新,导致useEffect无法触发更新子菜单状态。 open属性位置错误:将控制展开的open属性加在了MenuItem上,而非对应的SubMenu组件。- 缺少根路径映射:根路径
/未在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> </> ); }
关键修改点
- 监听路由变化:移除多余的
path状态,直接监听location.pathname的变化,确保路由切换时能实时更新子菜单状态。 - 调整
open属性位置:将open属性从MenuItem移到对应的SubMenu组件,控制子菜单的展开/收起。 - 补充根路径映射:在
routeMenuKeys中添加"/": "home",让Dashboard页面能匹配到Home子菜单。 - 添加激活状态标记:给每个
MenuItem添加active属性,根据当前路由判断是否激活,提升用户体验。
内容的提问来源于stack exchange,提问作者Reacting
相关产品推荐
相关产品推荐

