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

React Router V6如何禁止直接访问子路由并重定向至父路由

问题与需求

现有React Router路由配置如下:

<Route path={`/home`} element={<PrivateRoute />}>
    <Route
        index={true}
        element={<Home />}
    />
    <Route path={`settings`} element={<Settings />} />
</Route>

需求:禁止用户直接从浏览器地址栏访问/home/settings这类子路由,一旦直接访问需自动重定向到/home。该需求与身份认证无关,此前尝试用上下文存储访问路径的方案可维护性差,需要更合理的实现方式。

解决方案

方案一:路由守卫+会话存储标记(支持子路由刷新)

通过创建路由守卫组件,结合会话存储标记用户是否已访问过父路由/home,实现子路由访问控制:

  1. 创建路由守卫组件
import { useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';

const HomeChildRouteGuard = ({ children }) => {
  const location = useLocation();
  const navigate = useNavigate();

  useEffect(() => {
    // 检查是否有来自/home的导航标记或会话存储标记
    const hasVisitedHome = location.state?.fromHome || sessionStorage.getItem('hasVisitedHome');
    
    if (!hasVisitedHome) {
      // 重定向到/home,避免循环重定向
      navigate('/home', { replace: true, state: { fromRedirect: true } });
    }
  }, [location, navigate]);

  return children;
};
  1. 修改Home组件,添加访问标记
import { useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';

const Home = () => {
  const location = useLocation();
  const navigate = useNavigate();

  useEffect(() => {
    // 首次进入/home时设置会话存储标记
    if (!location.state?.fromRedirect) {
      sessionStorage.setItem('hasVisitedHome', 'true');
    }

    // 离开/home时清除标记
    return () => {
      sessionStorage.removeItem('hasVisitedHome');
    };
  }, [location]);

  // 导航到子路由时带上来源标记
  const goToSettings = () => {
    navigate('/home/settings', { state: { fromHome: true } });
  };

  return (
    <div>
      <h1>首页</h1>
      <button onClick={goToSettings}>进入设置</button>
    </div>
  );
};
  1. 更新路由配置,用守卫包裹子路由
<Route path={`/home`} element={<PrivateRoute />}>
    <Route
        index={true}
        element={<Home />}
    />
    <Route path={`settings`} element={
      <HomeChildRouteGuard>
        <Settings />
      </HomeChildRouteGuard>
    } />
</Route>

方案二:导航类型判断(不支持子路由刷新)

如果不需要允许子路由刷新,可以通过导航类型判断直接访问行为:

import { useEffect } from 'react';
import { useLocation, useNavigate, useNavigationType } from 'react-router-dom';

const HomeChildRouteGuard = ({ children }) => {
  const location = useLocation();
  const navigate = useNavigate();
  const navigationType = useNavigationType();

  useEffect(() => {
    // 如果是直接打开/刷新页面(POP类型)且无来源标记,重定向到/home
    if (navigationType === 'POP' && !location.state?.fromHome) {
      navigate('/home', { replace: true });
    }
  }, [location, navigate, navigationType]);

  return children;
};

之后同样将子路由用该守卫组件包裹即可,此方案下刷新子路由会被重定向回/home。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 06:40:21