用react hooks实现一个全局路由拦截(一)

react hooks 已经盛行一段时间。最新的react-router-dom 和react-redux也都同时支持了hooks写法。我们可以抛弃 withRouter轻松获取location等对象,也再也无须写mapStateToProps和mapDispatchToProps。下面我们结合react-router-dom实现一个简单的登录验证和全局拦截实例。

注意:react版本至少要16.8,

本实例基础库版本如下:

"react": "^17.0.1",

    "react-dom": "^17.0.1",

    "react-router": "^5.2.0",

    "react-router-dom": "^5.2.0",

    "react-scripts": "4.0.0",

先捋一下我们要实现的基本效果:

1 根路由是login页面。如果没有登录,同时该页面设置了某个属性,我们暂且把它设置为auth,也就是该页面需要被拦截。那么我们需要把它重定向到登录页面,

如果它不要被拦截。则直接定位404。

2如果已经登录,我们在每次页面路径切换的时候,需要看当前的页面路径是否是login,如果是login,则我们需要把它重定向到首页,比如home。一般登录以后我们是不允许再回到登录页。而如果当前的页面地址不存在,我们则要果断定位到404。

基本逻辑清晰了以后,我们开始写基本逻辑和配置

项目结构:

App.js

router

   ----authRoute.js   

   -----routes.js

-------------------------------------app.js-----------------------------------------------------------

import { BrowserRouter as Router, Switch, Route } from "react-router-dom"

import routes from "./router/routes"

import AuthRoute from "./router/authRoute"

function App() {

  return (

    

      

        {

          routes.map((item, index) => { 

            return (

              

            )

          })

        }

      

    

  );

}

import React from 'react'

 

import Home from "../pages/Home"

import Login from "../pages/Login"

import About from "../pages/About"

import NotFound from "../pages/NotFound"

-------------------------------------------routes.js----------------------------------------------------------

const routes = [

    { name: "", path: "/", component:Login,exact:true},

    { name: "login", path: "/login", component:Login,exact:false},

    { name: "home", path: "/home", component:Home,auth:true,exact:false},

    { name: "about", path: "/about", component: About,auth:true, exact: false },   

    { name: "404", path: "/404", component: NotFound, exact: false },   

]

export default routes;

-------------------------------------------authRoute.js----------------------------------------------------------

import React from 'react'

import { Redirect, Route } from "react-router-dom"

const  AuthRoute = (props) => { 

    let { location, routeData } = props

    let { pathname } = location

    const isLogin = localStorage.getItem("isLogin")

    //当前路径所在的路由item信息

    const targetRouteObj = routeData.find((item) => item.path == pathname)

    //未登录,路径存在,且不需要拦截则直接进入该页面 

    if (targetRouteObj && !targetRouteObj.auth && !isLogin) { 

        let { component } = targetRouteObj

        return 

    }

    //登录

    if (isLogin) {

        // 如果要进入登录页面

        if (pathname == "/login") {

            return 

        } else {

            //页面地址存在

            if (targetRouteObj) {

                return  

            } else { 

               //页面地址不存在 

               return 

            }

        }

    } else {

        if (targetRouteObj && targetRouteObj.auth) {

            return 

        } else { 

            return 

        }

    }

}

export default AuthRoute

----------------------------------------login.js------------------------------------------------------------

import React, { useState } from 'react'

import { useHistory} from "react-router-dom"

import "./login.css"

function Login() { 

    const [user,setUser]=useState("")

    const [password, setPassword] = useState("")

    let history=useHistory()

    const getVal = (obj) => { 

        let type = obj.target.dataset.type

       

        if (type == "user") {

            setUser(obj.target.value)

        } else { 

            setPassword(obj.target.value)

        }        

    }

    const login = (props) => { 

        localStorage.setItem("isLogin", true)   

        history.push("/home")

    }

    return (

        

            

                

            

            

                

            

            

用户名是:{ user}

            

密码是:{ password}

            

                

            

        

    )

}

export default Login

接下来我们解释一下基本逻辑

routes.js是我们路由配置的数组,这里我们给需要拦截的页面添加了一个auth熟悉。auth:true,表示该页面需要拦截验证,否则不需要。我们把login和404除掉了这个配置,authRoute是我们封装的一个Route组件。我们最后需要导出一个Route组件,最后挂到app.js的switch中,

每次页面切换的时候,我们都获取到当前path所对应的一条json信息。根据我们之前的逻辑。如果未登录。我们需要判断当前页面是否设置了拦截处理标志,如果登录了,我们需要判断下当前的页面路径是否是千万登录页。亦是否是一个根本不存在的页面。我们做相应的逻辑处理。最后在app.js中。我们不再用Route,而采用封装了逻辑的AuthRoute 。这样就可以实现全局路由拦截。

本实例中我们采用了react-router-dom 的hooks。useHistory()获取到路由实例对象。直接通过它的replace和push实现重定向

 

你可能感兴趣的:(react,hooks,react,路由拦截,reactjs)