携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情
前言
大家好呀,我是L同学。在上篇文章react笔记(二十)—— 配置路径别名中,我们学习了配置路径别名、@别名路径提示、通过redux实现登录功能等相关知识点。在本篇文章中,我们将学习到项目中经常用到的知识点,包括非组件获取路由信息、路由鉴权等相关知识点。
非组件获取路由信息
在项目中我们经常在组件中进行路由跳转。所以我们在App.js中引入BrowserRouter、Route等信息,定义路由信息。
import {BrowserRouter as Router, Route, Switch, Redirect} from 'react-router-dom'
function App() {
return (
<Router>
<div className='app'>
<Switch>
<Redirect exact from='/' to="/home" ></Redirect>
{/* <Route exact path='/' component={Layout}></Route> */}
<Route path='/home' component={Layout}></Route>
<Route path='/login' component={Login}></Route>
<Route>
<NotFound />
</Route>
</Switch>
</div>
</Router>
)
}
然后在组件中通过使用useHistory进行路由跳转。
import { useHistory } from "react-router-dom"
...
const history = useHistory()
history.push('/home')
当处理token失效问题时,我们通常在响应拦截器中进行处理。当响应错误error.response.status为401时,通常进行如下操作: 提示用户登陆信息已过期、清除存储在redux和localstorage中的token、跳转到登录页。第一步和第二步处理是简单的,那么第三步我们怎么在非组件环境中拿到路由信息,进行相应的路由跳转等操作呢?
我们需要使用路由中提供的Router组件,并自定义history对象。
首先我们在utils文件夹中创建history.js文件,导入创建自定义history的函数。
import {createBrowserHistory} from 'history'
const history = createBrowserHistory()
export default history
然后,我们在App.jsh中导入Router组件,添加history属性。
import {Router, Redirect, Route, Switch} from 'react-router-dom'
然后在
import history from './utils/history'
function App() {
return (
<Router history={history}>
<div className='app'>
<Switch>
<Redirect exact from='/' to="/home" ></Redirect>
{/* <Route exact path='/' component={Layout}></Route> */}
<Route path='/home' component={Layout}></Route>
<Route path='/login' component={Login}></Route>
<Route>
<NotFound />
</Route>
</Switch>
</div>
</Router>
)
}
这时,我们可以在非组件环境响应拦截器中使用自定义的history进行路由跳转。
在request.js文件中。
import { getToken } from './storage';
import store from '@/store'
import history from './history';
// 添加响应拦截器
instance.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
if(error.response.status === 401) {
console.log('history', history);
message.error('登录信息过期', 1)
store.dispatch(logout())
history.replace({
pathname: '/login',
state: {
from: history.location.pathname
}
})
}
return Promise.reject(error);
});
路由鉴权
Route组件中,可以传component,代表对应的path渲染对应的组件。
<Route path="/login" component={Login}></Route>
除了传component,还可以传render,render接收一个函数。
<Route path="/login" render={() => <Login />}></Route>
还可以这样书写。
<Route path='/home'>
<Layout></Layout>
</Route>
在pc端后台管理项目中,我们要进行登陆访问控制。若用户没有登陆(也就是没有token),是访问不了首页的。所以我们可以在render中进行条件判断。
当路径为/home时, 首先会判断是否有token, 有的话就渲染Layout组件,没有的话就重定向到登陆页面。
<Route path='/home' render={() => {
const token = getToken()
if(token) {
return <Layout />
}else {
return <Redirect to='/login'></Redirect>
}
}}></Route>
我们可以封装自己的PrivateRoute组件。最后使用的时候跟Route组件一样的使用。
<PrivateRoute path="/home" component={Layout}></PrivateRoute>
或者这样使用。
<PrivateRoute path="/home">
<Layout></Layout>
</PrivateRoute>
首先,创建/component/PrivateRoute/index.js文件
import { getToken, hasToken } from '@/utils/storage'
import React from 'react'
import {Redirect, Route} from 'react-router-dom'
export default function PrivateRoute({children, component:Component, ...rest}) {
return (
<Route {...rest} render={() => {
if(hasToken()) {
return children ? children : <Component></Component>
}else {
return <Redirect to={{
pathname: '/login'
}}></Redirect>
}
}}></Route>
)
}