React判断无token状态的问题

在平时的项目中,做到登陆的一个状态,就会遇到在没有等登陆的情况下不让其访问其它页面,和在token过期的情况下应该要返回login页面的业务问题,这边带大家如何实现这些业务问题,并用发布订阅来来实现在token过期的情况下应该返回login页面的业务问题

一、没有token不让其访问页面

在vue中有路由守卫来实现这个功能,但是在react中是没有路由守卫了,需要自己来写;在react可以使用useNavigate的replace覆盖历史和useEffect来实现

在需要首页的跟目录中写入即可

import React,{useEffect} from 'react'
import {Outlet,useNavigate} from "react-router-dom"
export default function Apps() {
    const navigate= useNavigate()
    const token =sessionStorage.getItem("token")
    useEffect(()=>{
        if(!token){
          // 当没有token的时候就返回登陆页,并且只执行一次
          console.log("请先登陆");
          navigate("/login",{replace:true})// replace:true 覆盖历史 
        }
      },[])
  // 判断当有token 的时候就进入页面,
  if(token){
    return (
      <>
       {/* Outle 显示子路由,在react-router-dom中引入,和vue的<router-view/>一个道理 */}
       <Outlet/>
      </>
    )
  }else{
    return <></>
  }
}

像上面这个样子就可以实现在没有token的情况下不让其访问首页

二、token过期返回login页面

1、首先先创建一个全新的文件夹,写入发布订阅的代码,然后导出

interface IEvents {
  [index: string]: Array<Function>;
}
interface IEventBus {
  events: IEvents;
  on: (key: string, func: Function) => void;
  emit: (key: string) => void;
}

// 设计模式是编程思想,跟语言无关
// 原理: 把一些函数,放到一个数组里面,后面需要使用的时候通过数组直接取出,调用
const EventBus: IEventBus = {
  events: {},
  // 订阅事件的方法
  //
  on(key: string, func: Function) {
    // 使用key对应一个数组,数组里面存着所有的函数
    if (!this.events[key]) {
      this.events[key] = [];
    }
    this.events[key].push(func);
  },
  // 发布事件的方法
  emit(key: string) {
    this.events[key].forEach((func) => func());
  },
};
export default EventBus;

2、在axios拦截器响应错误的地方拿到错误的状态值,然后删除token和订阅一下上面的代码

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios"
import EventBus from "../util/EventBus";

const instance: AxiosInstance = axios.create({
  baseURL:"http://localhost:8080", 
  timeout: 5000
});

// 添加请求拦截器
instance.interceptors.request.use(function (config: AxiosRequestConfig<any>) {
  let token = sessionStorage.getItem("token") as string
  if (token) {
    config.headers = config.headers || {}
    config.headers["xxx"] = token
  }
  // 在发送请求之前做些什么
  return config;
}, function (error: any) {
  // 对请求错误做些什么
  return Promise.reject(error);
});

// 添加响应拦截器
instance.interceptors.response.use(function (response: AxiosResponse<any, any>) {
  // 对响应数据做点什么
  return response.data;
}, function (error: any) {
//这里是响应错误时返回的数据,在这边操作即可
    let err=error.response.data.errCode
  if(err===1001||err===1002){
    // 这里是发布,在相对于的页面里面订阅
    sessionStorage.removeItem("token")
    EventBus.emit("loginTimeout")
  }

  // 对响应错误做点什么
  return Promise.reject();
});
export default instance

然后来到首页的跟目录页面,在这里订阅

import React,{useEffect} from 'react'
import {Outlet,useNavigate} from "react-router-dom"
import EventBus from "./util/EventBus";
export default function Apps() {
    const navigate= useNavigate()
    const token =sessionStorage.getItem("token")
    useEffect(()=>{
        if(!token){
          // 当没有token的时候就返回登陆页,并且只执行一次
          console.log("请先登陆");
          navigate("/login",{replace:true})// replace:true 覆盖历史 
        }
      },[])



      //订阅发布的代码
     EventBus.on("loginTimeout", function () {
    // 如果登录失效 1.弹出提示  2.跳转到login
     const.log("登录失效")
    navigate("/login", { replace: true });
  });



  // 判断当有token 的时候就进入页面,
  if(token){
    return (
      <>
       {/* Outle 显示子路由,在react-router-dom中引入,和vue的<router-view/>一个道理 */}
       <Outlet/>
      </>
    )
  }else{
    return <></>
  }
}

好了,这样你就已经完成,如有不懂或有不足之处欢迎大家留言讨论

猜你喜欢

转载自blog.csdn.net/L_yupeng/article/details/128821672