如何基于条件禁用React Router路由且保留对应菜单项
实现方案
核心思路是将路由配置与菜单逻辑解耦,统一维护路由元数据,既保留菜单项,又能基于路由的element状态控制禁用状态,同时处理路由跳转的兜底逻辑。
步骤1:抽离统一的路由配置数组
把分散的路由定义抽成单独的数组,方便菜单和路由组件共用,避免重复维护:
// 可单独放在 routes-config.js 文件中,也可在 DashboardPage 同文件定义 import { Navigate } from 'react-router-dom'; import { SalesOverviewNewPage } from "./inner-components"; export const dashboardRoutes = [ { path: "/", element: <Navigate replace to="sales-overview-new" />, hidden: true }, // 根路由在菜单中隐藏 { path: "/sales-overview-new", element: <SalesOverviewNewPage />, label: "销售概览" }, { path: "/devices-overview", element: null, label: "设备概览" }, { path: "/perfomance", element: null, label: "性能分析" }, { path: "/sales-datewise", element: null, label: "按日期销售" }, { path: "/top-items-more", element: null, label: "热门商品详情" }, ];
步骤2:重构路由渲染逻辑
基于路由数组生成Routes,同时为element: null的路由设置兜底页面(比如功能未开放提示):
import React from 'react'; import { Route, Routes } from 'react-router-dom'; import { dashboardRoutes } from './routes-config'; // 兜底的功能未开放页面 const UnavailablePage = () => ( <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}> <p>该功能暂未开放,敬请期待</p> </div> ); export const DashboardPage = (props) => { return ( <div className="flexRow full p-0 m-0"> {/* 引入你的菜单组件,传入路由配置 */} <SidebarMenu routes={dashboardRoutes} /> <div className='full-flex flexCol width100 p-0 m-0'> <Routes> {dashboardRoutes.map((route, idx) => ( <Route key={idx} path={route.path} // 若element为null,渲染兜底页面 element={route.element ?? <UnavailablePage />} /> ))} </Routes> </div> </div> ) }
步骤3:实现带禁用逻辑的菜单组件
遍历路由数组生成菜单项,根据element是否为null判断禁用状态,通过样式和事件阻止实现不可点击:
import { NavLink } from 'react-router-dom'; const SidebarMenu = ({ routes }) => { return ( <div className="sidebar-menu"> {/* 过滤掉需要隐藏的路由(比如根路由) */} {routes.filter(route => !route.hidden).map((route, idx) => { const isDisabled = route.element === null; return ( <div key={idx} className={`menu-item ${isDisabled ? 'disabled' : ''}`}> <NavLink to={route.path} // 禁用时阻止跳转行为 onClick={e => isDisabled && e.preventDefault()} className={({ isActive }) => `menu-link ${isActive ? 'active' : ''} ${isDisabled ? 'disabled-link' : ''}` } > {route.label} </NavLink> </div> ); })} </div> ); };
步骤4:添加禁用样式
通过CSS让禁用的菜单项视觉上区分,同时彻底阻止交互:
/* 禁用的菜单项样式 */ .menu-item.disabled { opacity: 0.6; pointer-events: none; /* 直接阻止所有点击事件,比onClick拦截更彻底 */ } .menu-link.disabled-link { color: #999; cursor: not-allowed; }
补充说明
- 这种方式保证了路由和菜单的配置统一,后续新增/修改路由只需维护
dashboardRoutes数组即可; - 即使用户手动在地址栏输入禁用路由的URL,也会跳转到兜底提示页面,不会出现空白;
- 若需要基于其他统一条件(比如权限)禁用,只需在路由数组中添加
disabled字段,菜单中判断该字段即可,扩展性强。
内容的提问来源于stack exchange,提问作者bugsmasher
相关产品推荐
相关产品推荐

