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

React路由访问限制实现:需先访指定路径且用Context管理状态

实现方案

核心思路是用Context管理访问状态,结合sessionStorage实现刷新持久化(你排除了localStorage,sessionStorage是前端轻量的替代方案,页面刷新后数据保留,关闭标签页才清除),再配合React Router的路由守卫控制路由访问权限。

1. 创建访问状态Context

定义Context存储已访问路由列表,同时实现状态的更新与持久化同步:

import { createContext, useContext, useState, useEffect, useMemo } from 'react';

const RouteAccessContext = createContext();

export function RouteAccessProvider({ children }) {
  // 从sessionStorage初始化状态,页面刷新时恢复数据
  const [visitedRoutes, setVisitedRoutes] = useState(() => {
    const saved = sessionStorage.getItem('visitedRoutes');
    return saved ? JSON.parse(saved) : [];
  });

  // 状态变化时同步到sessionStorage
  useEffect(() => {
    sessionStorage.setItem('visitedRoutes', JSON.stringify(visitedRoutes));
  }, [visitedRoutes]);

  // 标记路由为已访问
  const markRouteAsVisited = (routePath) => {
    if (!visitedRoutes.includes(routePath)) {
      setVisitedRoutes(prev => [...prev, routePath]);
    }
  };

  // 检查是否已访问指定路由
  const hasVisitedRoute = (routePath) => {
    return visitedRoutes.includes(routePath);
  };

  // 用useMemo优化,避免不必要的组件重渲染
  const contextValue = useMemo(() => ({
    visitedRoutes,
    markRouteAsVisited,
    hasVisitedRoute
  }), [visitedRoutes]);

  return (
    <RouteAccessContext.Provider value={contextValue}>
      {children}
    </RouteAccessContext.Provider>
  );
}

// 自定义钩子,简化组件调用
export function useRouteAccess() {
  return useContext(RouteAccessContext);
}

2. 包裹应用根组件

将整个应用用RouteAccessProvider包裹,确保所有路由和组件能访问Context状态:

import { RouteAccessProvider } from './RouteAccessContext';
import { BrowserRouter } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      <RouteAccessProvider>
        {/* 你的路由和业务组件 */}
      </RouteAccessProvider>
    </BrowserRouter>
  );
}

export default App;

3. 实现路由守卫组件

创建ProtectedRoute组件,用于校验用户是否满足访问条件:

import { Navigate, Outlet } from 'react-router-dom';
import { useRouteAccess } from './RouteAccessContext';

// requiredRoute:必须访问过的前置路由;fallbackPath:权限不足时跳转的路径
export function ProtectedRoute({ requiredRoute, fallbackPath = '/' }) {
  const { hasVisitedRoute } = useRouteAccess();
  const isAllowed = hasVisitedRoute(requiredRoute);

  return isAllowed ? <Outlet /> : <Navigate to={fallbackPath} replace />;
}

4. 标记前置路由访问状态

在需要追踪访问状态的前置路由组件中,调用markRouteAsVisited更新状态:

import { useEffect } from 'react';
import { useRouteAccess } from './RouteAccessContext';

function PreRoute() {
  const { markRouteAsVisited } = useRouteAccess();

  useEffect(() => {
    // 标记当前路由为已访问
    markRouteAsVisited('/pre-route');
  }, [markRouteAsVisited]);

  return <div>这是前置路由,访问后才能进入目标路由</div>;
}

export default PreRoute;

5. 配置路由规则

在路由配置中用ProtectedRoute包裹需要权限的路由:

import { Routes, Route } from 'react-router-dom';
import PreRoute from './PreRoute';
import TargetRoute from './TargetRoute';
import Home from './Home';
import { ProtectedRoute } from './ProtectedRoute';

function RoutesConfig() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/pre-route" element={<PreRoute />} />
      {/* 只有访问过/pre-route,才能进入/target-route */}
      <Route element={<ProtectedRoute requiredRoute="/pre-route" fallbackPath="/pre-route" />}>
        <Route path="/target-route" element={<TargetRoute />} />
      </Route>
    </Routes>
  );
}

export default RoutesConfig;

关键细节说明

  • 若需要跨标签页共享访问状态,可将sessionStorage替换为cookie;若仅需单标签页内持久化,sessionStorage足够轻量。
  • 确保标记的路由路径与路由配置中的路径完全一致(比如带斜杠、参数格式),避免匹配失败。
  • 若应用规模较大,可结合useCallback优化markRouteAsVisited方法,进一步减少重渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 18:42:35