基于React Router6 TS实现路由守卫

发布于:2024-04-17 ⋅ 阅读:(176) ⋅ 点赞:(0)

定义路由表

import {BrowserRouter, Route, RouteObject, Routes,} from "react-router-dom";
import {Home, Login, NotFound} from "@/views";
import {RouterGuard} from "@/routers/router_guard.tsx";
import {ReactNode} from "react";
import {Test} from "@/views/test/test.tsx";
import {LOGIN_PATH} from "@/utils/constant";
import {Broken} from "@/views/Broken/broken.tsx";

type AuthRouteObject = {
    needAuth?: boolean
}

const router: RouteObject[] & AuthRouteObject[] = [
    {
        path: "/",
        element: <Home></Home>,
        needAuth: true,
        children:[
            {
                path: "/test",
                element: <Test/>,
            }
        ]
    },
    {
        path: LOGIN_PATH,
        element: <Login></Login>,
        needAuth:true
    },
    {
        path:"/500",
        element:<Broken></Broken>
    },
    {
        path: "*",
        element: <NotFound></NotFound>
    }
]


export const RenderRouters = () => {
    const traverseRoutes = (router: RouteObject[] & AuthRouteObject[]) => {
        return router.map((route: RouteObject & AuthRouteObject): ReactNode => {
            const element =  <RouterGuard needAuth={route?.needAuth} element={route.element}/>
            if(Array.isArray(route.children) && route.children.length>0){
                return (
                    <Route path={route.path} element={element} key={route.path}>
                        {traverseRoutes(route.children)}
                    </Route>
                )
            }
            return <Route path={route.path} element={element} key={route.path}/>
        })
    }
    return (
        <>
            <BrowserRouter>
                <Routes>
                    {traverseRoutes(router)}
                </Routes>
            </BrowserRouter>
        </>
    )
}

定义守卫组件

import {PropsWithChildren, ReactNode} from "react";
import {useUserStore} from "@/store/user_store";
import {Navigate, useLocation} from "react-router-dom";
import {LOGIN_PATH} from "@/utils/constant";

interface Props extends PropsWithChildren {
    element: JSX.Element | ReactNode
    needAuth?:boolean
}

export const RouterGuard = (props: Props): JSX.Element | React.ReactNode => {
    const userStore = useUserStore()
    const pathName = useLocation().pathname
    const token = userStore.token
    if (!props.needAuth){
        return props.element
    }
    if (token && pathName == LOGIN_PATH){
        return <Navigate to="/" replace></Navigate>
    }
    if (!token && pathName !== LOGIN_PATH) {
        return <Navigate to={LOGIN_PATH} replace></Navigate>
    }
    return props.element
}

使用

import './App.css'
import {RenderRouters} from "@/routers/router.tsx";

function App() {
    return (
        <>
            <RenderRouters></RenderRouters>
        </>
    )
}

export default App

效果展示

请添加图片描述


网站公告

今日签到

点亮在社区的每一天
去签到