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

如何基于条件禁用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:57:47