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

react-router-dom v6 登录状态路由重定向问题排查与实现

React Router v6 路由权限控制实现方案

适用场景

项目采用ReactJS搭配Laravel API开发,需要实现两类路由访问限制:

  • 已登录用户访问/login、/register等游客专属页面时,自动重定向到首页
  • 未登录用户访问首页等受保护路由时,自动重定向到登录页

报错原因拆解

  1. 首次编写代码抛出Uncaught Error: [Navigate] is not a <Route> component错误,核心原因是react-router-dom v6对路由结构有强制约束:<Routes>组件的直接子元素只能是<Route>组件。第一次的写法直接在<Route path="/login">的标签子节点里放了<Navigate>组件,违反了结构要求;同时代码还存在两个低级问题:重复声明了两个path="/login"的父路由、把注册页路由嵌套在/login父路由下,就算不抛错,注册页实际访问路径也会变成/login/register,和预期的/register完全不符。
  2. 第二次修改后未登录访问受保护路由不跳转,原因非常直接:只给/login路由加了「已登录跳首页」的判断,完全没给首页等受保护路由加「未登录跳登录页」的拦截逻辑,自然不会触发重定向。

正确实现步骤

不要在路由配置里零散写三元判断,封装两个可复用的路由守卫组件,既符合v6的路由结构要求,也方便后续维护。

1. 封装两类路由守卫

首先封装游客路由守卫(给登录、注册页使用):

// components/GuestRoute.jsx
import { Navigate } from "react-router-dom";

export default function GuestRoute({ children }) {
  // 读取本地存储的登录令牌判断登录状态
  const isLoggedIn = !!localStorage.getItem("auth_token");
  // 已登录直接替换路由跳转到首页,未登录则正常渲染子页面
  return isLoggedIn ? <Navigate to="/" replace /> : children;
}

再封装受保护路由守卫(给需要登录才能访问的业务页面使用):

// components/ProtectedRoute.jsx
import { Navigate } from "react-router-dom";

export default function ProtectedRoute({ children }) {
  const isLoggedIn = !!localStorage.getItem("auth_token");
  // 未登录直接替换路由跳转到登录页,已登录则正常渲染子页面
  return isLoggedIn ? children : <Navigate to="/login" replace />;
}

注意:<Navigate>组件一定要加replace属性,替换当前路由历史记录,避免用户点击浏览器返回键时重复进入重定向循环。

2. 按规范配置路由

所有路由判断逻辑都放在<Route>的element属性内,严格遵守v6的路由结构要求:

// router/index.jsx
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import Login from "../pages/Login";
import Register from "../pages/Register";
import Main from "../pages/Main";
import GuestRoute from "../components/GuestRoute";
import ProtectedRoute from "../components/ProtectedRoute";

export default function AppRouter() {
  return (
    <Router>
      <Routes>
        {/* 受保护路由:登录后才可访问 */}
        <Route
          path="/"
          element={
            <ProtectedRoute>
              <Main />
            </ProtectedRoute>
          }
        />
        {/* 游客路由:仅未登录时可访问 */}
        <Route
          path="/login"
          element={
            <GuestRoute>
              <Login />
            </GuestRoute>
          }
        />
        <Route
          path="/register"
          element={
            <GuestRoute>
              <Register />
            </GuestRoute>
          }
        />
      </Routes>
    </Router>
  );
}

补充说明

如果后续把登录状态存到Context、Redux等响应式状态容器里,只需要修改两个守卫组件里的登录状态读取逻辑即可,路由配置不需要做任何改动;不要直接在<Routes>或者<Route>的子节点位置放除了<Route>之外的其他组件,否则会持续触发路由结构类报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:24:24