React react-router v6 路由守卫

293 阅读2分钟

useRouters 的使用

  • 动态地配置路由

  • 接收一个路由数组,用匹配到的路由来渲染相应的组件

  • 在应用的生命周期中更改路由更容易

  • Routes包裹Route组件(react-router v6强制要求)

文件结构

  • router

    • index.tsx:存放路由数组
    import { message } from "antd";
    import { useEffect } from "react";
    import { useSelector } from "react-redux";
    import { matchRoutes, useLocation, useNavigate } from "react-router-dom";
    import { routers } from "./index";
    
    const AuthRoute = ({ children, auth }: any) => {
      const navigate = useNavigate();
      const token = localStorage.getItem("blogToken") || "";
      const loginState = useSelector((state: any) => state.public.loginState);
      const mathchs = matchRoutes(routers, location);
    
      const isExist = mathchs?.some((item) => item.pathname == location.pathname);
    
      useEffect(() => {
        if (token == "" && auth) {
          message.error("token 过期,请重新登录!");
          navigate("/login");
        }
        // 这里判断条件是:token 存在并且是匹配到路由并且是已经登录的状态
        if (token && isExist && loginState == "login") {
          // 如果你已经登录了,但是你通过浏览器里直接访问login的话不允许直接跳转到login路由,必须通过logout来控制退出登录或者是token过期返回登录界面
          if (location.pathname == "/" || location.pathname == "/login") {
            navigate("/home");
          } else {
            // 如果是其他路由就跳到其他的路由
            navigate(location.pathname);
          }
        }
      }, [token, location.pathname]);
    
      return children;
    };
    export default AuthRoute;
    
    • AuthRouter:路由权限控制
    import { message } from "antd";
    import { useEffect } from "react";
    import { useSelector } from "react-redux";
    import { matchRoutes, useLocation, useNavigate } from "react-router-dom";
    import { routers } from "./index";
    
    const AuthRoute = ({ children, auth }: any) => {
      const navigate = useNavigate();
      const token = localStorage.getItem("blogToken") || "";
      const loginState = useSelector((state: any) => state.public.loginState);
      const mathchs = matchRoutes(routers, location);
    
      const isExist = mathchs?.some((item) => item.pathname == location.pathname);
    
      useEffect(() => {
        if (token == "" && auth) {
          message.error("token 过期,请重新登录!");
          navigate("/login");
        }
        // 这里判断条件是:token 存在并且是匹配到路由并且是已经登录的状态
        if (token && isExist && loginState == "login") {
          // 如果你已经登录了,但是你通过浏览器里直接访问login的话不允许直接跳转到login路由,必须通过logout来控制退出登录或者是token过期返回登录界面
          if (location.pathname == "/" || location.pathname == "/login") {
            navigate("/home");
          } else {
            // 如果是其他路由就跳到其他的路由
            navigate(location.pathname);
          }
        }
      }, [token, location.pathname]);
    
      return children;
    };
    export default AuthRoute;
    
  • App.tsx

import { ReactNode, useCallback, useEffect, useState } from "react";
import { useSelector } from "react-redux";
import {
  Route,
  Routes,
} from "react-router-dom";
import { RouteConfig, routers } from "./router";
import AuthRoute from "./router/AuthRoute";

const App = () => {

  const loginState = useSelector((state: any) => state.public.loginState);

  // 处理我们的routers
  const RouteAuthFun = (
    (routeList: RouteConfig[]) => {
      return routeList.map(
        (item: {
          path: string;
          auth: boolean;
          element: ReactNode;
          children?: any;
        }) => {
          return (
            <Route
              path={item.path}
              element={
                <AuthRoute auth={item.auth} key={item.path}>
                  {item.element}
                </AuthRoute>
              }
              key={item.path}
            >
              {/* 递归调用,因为可能存在多级的路由 */}
              {item?.children && RouteAuthFun(item.children)}
            </Route>
          );
        }
      );
    }
  );
  return <Routes>{RouteAuthFun(routers)}</Routes>;
};
export default App;

链接:juejin.cn/post/719557…