Vue 用户提问:如何在 React 中实现全局路由守卫?
前言
如果想在 vue 中实现全局路由守卫,只需要在 beforeEach 中写路由守卫逻辑即可。
但是如果使用 react 的话,应该怎么做呢?
在 react 中,其实是没有 beforeEach 的,如果需要实现路由守卫,需要结合 ReactRoute 路由库,自己手动搓一个路由守卫。
需求
我的这个管理系统对于路由守卫的要求相对简单,需求如下:
- 进入博客管理系统,判断是否登录,未登录则跳转登录页(/login)
- 如果已经登录,则跳转管理页面(/mangement)
- 如果已经登录但是不能匹配到路径,则跳转 404 页面(/404)
最主要的功能还是 1 和 2,如果你已经明白需求了,那就继续往下看吧!
实现
基本路由
如果不使用路由守卫,如何在 react 中实现路由?
文档如下:
我们先按着文档实现一个基本的路由格式,在 app.tsx 中实现如下:
//app.tsx
import React from "react";
import { BrowserRouter as Router } from "react-router-dom";
import GetRouter from "./components/getRouter";
const App = () => {
return (
<Router>
<GetRouter />
</Router>
);
};
export default App;
我简单的把路由信息进行了封装,下面是 GetRouter 文件:
//./components/getRouter
import { useRoutes } from "react-router-dom";
import routes from "../router";
export default function GetRouter() {
let element = useRoutes(routes);
return element;
}
routes 文件如下:
// ../router
import { lazy } from "react";
const Management = lazy(() => import("../views/management"));
const Login = lazy(() => import("../views/login"));
const Error = lazy(() => import("../views/404"));
const About = lazy(() => import("../views/about"));
const routes = [
{
path: "/",
element: <Login />,
},
{
path: "/login",
element: <Login />,
},
{
path: "/management",
element: <Management />,
},
{
path: "/404",
element: <Error />,
},
{
path: "/about",
element: <About />,
},
];
export default routes;
这样一个简单的路由就实现了
增加路由守卫
现在我们开始增加路由守卫,只需要把我们的路由信息传入到我们路由守卫组件中即可。
那接下来我们就着重分析一下 UseAuth 这个组件!
路由守卫组件
第一个需求
进入博客管理系统,判断是否登录,未登录则跳转登录页(/login)
先实现一个简单的逻辑,如果没有登录就重定向到登陆页面,我们从本地存储里面去取登录信息进行判断,不成立跳转到登陆页面,那么这样看似是可以的。
import React from "react";
import { Navigate, useLocation } from "react-router-dom";
export default function AuthRoute(props: { children: JSX.Element }) {
const isLogin = localStorage.getItem("isLogin");
if (!isLogin) {
return <Navigate to="/login" />;
}
}
但是,我们这样写了之后,会发现并没有重定向到登录页面,反而造成了程序死循环!
为什么呢?
可以这样理解,如果每次没有登录都跳转到登录页面,那跳转登录页之前,会再次进入路由守卫,路由守卫再次判断仍然没有登录,就这样循环下去,变成了死循环。。。。
怎么解决?
只需要判断是否登录,如果没有登录,返回当前页面即可。
但是又因为我们的链接默认打开是根路径 '/',所以这里需要加一个判断,如果没有登录并且当前是登录页才返回当前页面。
import React from "react";
import { Navigate, useLocation } from "react-router-dom";
export default function AuthRoute(props: { children: JSX.Element }) {
const location = useLocation();
const isLogin = localStorage.getItem("isLogin");
const currentPath = location.pathname;
const condition = currentPath === "/login" && !isLogin;
if (condition) {
return props.children;
}
if (!isLogin) {
return <Navigate to="/login" />;
}
return props.children;
}
现在可能有些朋友感觉迷了,我们再来理一下流程:
首先项目启动打开链接 http://localhost:8081
默认进入为 '/' 根路径
判断没有登录,重定向到登录页
此时为登录页,又进入路由守卫,仍然没有登录
此时路径为登录页,并且没有登录,条件成立,返回当前页面,避免死循环
最后函数需要无条件返回 props.children,也就是当前页面,要不然会报这个错误
可以看到我们直接打开链接就进入了登陆页面 login
第二个需求
如果已经登录,则跳转管理页面(/mangement)
如果前面都实现了这个就好做了,只需要判断是否登录,如果登录就重定向到登录页。
但是还是需要判断,如果当前为管理页面,并且已经登录就返回当前页面,防止一直路由守卫判断。
import React from "react";
import { Navigate, useLocation } from "react-router-dom";
export default function AuthRoute(props: { children: JSX.Element }) {
const location = useLocation();
const isLogin = localStorage.getItem("isLogin");
const currentPath = location.pathname;
const condition =
(currentPath === "/login" && !isLogin) ||
(currentPath === "/management" && isLogin);
if (condition) {
return props.children;
}
if (!isLogin) {
return <Navigate to="/login" />;
}
if (isLogin) {
return <Navigate to="/management" />;
}
return props.children;
}
第三个需求
如果已经登录但是不能匹配到路径,则跳转 404 页面(/404)
如果我在地址栏输入例如 /aaa 这样的路径,我本地是匹配不到的,但是这时已经登陆了,这个时候我希望可以跳转到 404 页面。
我们现在需要增加一个匹配路径功能。代码如下:
我们封装一个匹配路径函数,如果匹配不到则直接返回即可。
import routes from "../router";
function matchRoute(path: String) {
const findPath = routes.find((val) => val.path === path);
if (!findPath) {
return;
}
return findPath;
}
export default matchRoute;
引入 matchAuth 匹配函数后代码如下,如果没有匹配到则返回 404 页面,同样上面需要增加 404 页面的判断,否则会死循环。
import React from "react";
import matchAuth from "../utils/matchAuth";
import { Navigate, useLocation } from "react-router-dom";
export default function AuthRoute(props: { children: JSX.Element }) {
const location = useLocation();
const isLogin = localStorage.getItem("isLogin");
const condition =
(currentPath === "/login" && !isLogin) ||
(currentPath === "/management" && isLogin) ||
(currentPath === "/404" && isLogin);
const findPath = matchAuth(currentPath);
if (condition) {
return props.children;
}
if (!findPath && isLogin) {
return <Navigate to="/404" />;
}
if (!isLogin) {
return <Navigate to="/login" />;
}
if (isLogin) {
return <Navigate to="/management" />;
}
return props.children;
}
总结
在 react 中实现路由守卫和 vue 不同,vue 可以使用内置的前置路由守卫函数,react 需要自己实现,不过原理大致相同。
在 react 中实现路由守卫非常重要的一点就是:记得对可能造成死循环的路径进行判断,然后返回当前页面即可,否则使用不当可能会造成死循环。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南