前言
最近在学习 react 发现react 中没有像vue 那样有官方提供的路由守卫 。
问了下 豆包 、元宝 、千问 、ChatGPT 给的方案五花八门,对于新手来说很头疼。结合
这几个AI助手给的方案,简单整理下比较容易理解的方案。
高阶组件
高阶组件
简单来说:
- 它是一个纯函数(没有副作用)
- 接收一个组件作为参数
- 返回一个新的、增强后的组件
可以用一个通俗的比喻理解:HOC 就像一个 "组件加工厂",你把基础组件送进去,它给你返回一个添加了新功能(比如权限校验、数据请求、样式包装)的新组件。
javascript
/**
* 认证守卫
* React.FC是React.FunctionComponent 的简写,表示这是一个函数组件
* React.PropsWithChildren 表示这是一个包含子元素的props
*/
import { Navigate } from "react-router-dom";
import { loginUtil } from "../utils";
export const withAuthGuard = (
Component: React.FC<React.PropsWithChildren>,
requireAuth: boolean = true,
) => {
return (props: React.PropsWithChildren) => {
// 判断是否登录
const isLogin = loginUtil.isLogin();
// 需要登录但是未登录,跳转到登录界面
if (requireAuth && !isLogin) {
return <Navigate to="/login" replace />;
}
// 不需要登录但是已登录,跳转到首页
if (!requireAuth && isLogin) {
return <Navigate to="/home" replace />;
}
// 其他情况,渲染组件
return <Component {...props} />;
};
};
// 设置组件名称,便于调试
withAuthGuard.displayName = "withAuthGuard";
使用
javascript
import { Button } from "antd";
import { useNavigate } from "react-router-dom";
import { withAuthGuard } from "@/hoc";
const LoginInFc = () => {
const navigate = useNavigate();
// 登录
const submitLogin = () => {
console.log("登录");
localStorage.setItem("token", "123456");
navigate("/home");
};
return (
<div>
<Button type="primary" onClick={submitLogin}>
登录
</Button>
</div>
);
};
const LoginIn = withAuthGuard(LoginInFc, false);
export default LoginIn;
效果

注意
要与普通的容器组件进行区分,例如
javascript
// 1. 普通容器组件写法
const AuthWrapper = ({ children }) => {
const isAuthenticated = checkAuth(); // 检查权限逻辑
if (!isAuthenticated) {
return <Redirect to="/login" />;
}
return children; // 这里就是"插槽"
};
// 2. 使用方式
function App() {
return (
<AuthWrapper>
<Dashboard /> {/* 这就是 children */}
</AuthWrapper>
);
}
这其实类似与vue中的普通插槽