React v6 路由守卫


浅记一下
需求是除了登录注册页,进入其他页面都需要登录后才能进入

参照的官网的例子


routes/index.tsx

首先是路由表

在路由表里面定义一个auth 属性,用来判断当前页面是否需要登录权限

import { lazy, Suspense } from 'react'
import SignIn from '../pages/SignIn'
 
 interface Router {
   name?: string,
   path: string,
   auth:boolean,
   children?: Array<Router>,
   component: any
}
 
const router: Array<Router> = [
   {
    path: '/',
    component: SignIn,
    auth: false,
   },
   {
     path: '/signIn',
     auth: false,
     component: lazy(() => import('../pages/SignIn'))
   },
   {
     path: '/signUp',
     auth: false,
     component: lazy(() => import('../pages/SignUp'))
  },
  {
    path: '/recLists',
    auth: true,
    component: lazy(() => import('../pages/RecLists'))
  },
  {
    path: '/hotLists',
    auth: true,
    component: lazy(() => import('../pages/HotLists'))
  },
  {
    path: "/newsInfo/:id",
    name: "newsInfo",
    auth: true,
    component: lazy(() => import('../pages/NewsInfo'))
  },
  {
    path: '/mySelf',
    auth: true,
    component: lazy(() => import('../pages/MySelf'))
  },
  {
    path: '/404',
    auth: false,
    component: lazy(() => import('../pages/404'))
  },
]
 
 export default router

App.tsx

App 组件中注册路由
在这里区分auth,通过router.map遍历所有路由

auth值为false时,也就是(!item.auth),即不需要身份就可以进入的页面(登录和注册页),那么就渲染当前组件< item.component />

if (!item.auth) {
 return (
   <Route key={i} path={item.path} element={
     <Suspense fallback={
       <>
         <Skeleton.Title animated />
         <Skeleton.Paragraph lineCount={20} animated />
       </>
     }>
       < item.component />
     </Suspense>
   } />
 )

auth值为true时,也就是(item.auth),即需要身份就可以进入的页面(内容页),那么就通过RequireAuth函数判断是否有身份权限,如果有,渲染当前组件;如果没有,定位到登录

RequireAuth函数
这里我是通过是否有cookie判断的,在登录或者注册时候会存储一个cookie,退出登录时再删掉

function RequireAuth({ children }: { children: JSX.Element }) {
  let location = useLocation()
  if (!getCookie('openId')) {
    return <Navigate to="/signIn" state={{ from: location }} replace />;
  }

  return children;
}

渲染的代码如下

else {
  return (
    <Route key={i} path={item.path} element={
      <Suspense fallback={
        <>
          <Skeleton.Title animated />
          <Skeleton.Paragraph lineCount={20} animated />
        </>
      }>
        <RequireAuth>
          <item.component />
        </RequireAuth>
      </Suspense>
    }>
    </Route>
  )
}

总体的App.tsx代码如下
因为是懒加载,外层用Suspense 包一下

import './App.css';

import { Suspense } from 'react'
import { Navigate, Route, Routes, useLocation } from 'react-router-dom'
import { Skeleton } from 'antd-mobile'

import router from './routes' 
import { getCookie } from './assets/js/cookie';

function App() {
  return (
    <Routes>
      {
        router.map((item, i) => {
          if (!item.auth) {
            return (
              <Route key={i} path={item.path} element={
                <Suspense fallback={
                  <>
                    <Skeleton.Title animated />
                    <Skeleton.Paragraph lineCount={20} animated />
                  </>
                }>
                  < item.component />
                </Suspense>
              } />
            )
          } else {
            return (
              <Route key={i} path={item.path} element={
                <Suspense fallback={
                  <>
                    <Skeleton.Title animated />
                    <Skeleton.Paragraph lineCount={20} animated />
                  </>
                }>
                  <RequireAuth>
                    <item.component />
                  </RequireAuth>
                </Suspense>
              }>
              </Route>
            )
          }
        })
      }
    </Routes>
  );
}

function RequireAuth({ children }: { children: JSX.Element }) {
  let location = useLocation()
  if (!getCookie('openId')) {
    return <Navigate to="/signIn" state={{ from: location }} replace />;
  }
  return children;
}
export default App;


index.tsx

在这里引入App组件

import React, { Suspense }  from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Routes } from "react-router-dom";
import './index.css';
import App from './App';

import store from './redux/store'
import { Provider } from 'react-redux'

import './mock'

ReactDOM.render(
  /* 此处需要用Provider包裹App,目的是让App所有的后代容器组件都能接收到store */
  <Provider store={store}>
    <BrowserRouter>
      <App/>
    </BrowserRouter>
  </Provider>,
  document.getElementById('root')
);


附一个cookie

cookie.js

//  保存cookie
//  json 需要存储cookie的对象
//  days 默认存储多少天
export function setCookie(json, days) {
    // 设置过期时间
    let data = new Date(
        new Date().getTime() + days * 24 * 60 * 60 * 1000
    ).toUTCString();

    for (var key in json) {
        document.cookie = key + "=" + json[key] + "; expires=" + data
    }
}


// 获取cookie
// name 需要获取cookie的key
export function getCookie(name) {
    var arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
    if (arr != null) {
        return unescape(arr[2])
    } else {
        return null
    }
}


//  删除cookie
//  name 需要删除cookie的key
export function clearCookie(name) {
    let json = {};
    json[name] = '';
    setCookie(json, -1)
}

登录时候

let loginInfo = {
  LoginName: res.username,
  openId: "asfafsfsfsdfsdfsdfdsf"
}

setCookie(loginInfo, 7)

退出时候

clearCookie('LoginName')
clearCookie('openId')




React真不是人写的东西 是我太菜了

你可能感兴趣的:(react)