一、安装redux、redux-toolkit
npm install react-redux redux-localstorage-simple @reduxjs/toolkit -S
npm install @types/react-redux -D
二、redux 相关配置
1、 在src目录下新建stroe 目录,并创建index.ts
cd src
mkdir store
cd store
touch index.ts
2、 新建user目录
mkdir user
cd user
touch userSlice.ts
3、编辑userSlice.ts 对user的token 设置aciton state、reduce
import { createSlice } from '@reduxjs/toolkit'
export interface IUserInitialState {
token: string;
}
const userInitialState: IUserInitialState = {
token: '',
}
export const userSlice = createSlice({
name: 'user',// state name
initialState: userInitialState, // 默认值
reducers: {
setUserToken: (state, action) => {
state.token = action.payload;
}
}
})
export const { setUserToken } = userSlice.actions;
export default userSlice.reducer;
4、编辑store/index.ts 作为redux的入口文件
import { configureStore } from '@reduxjs/toolkit'
// 可以将需要的状态添加到localstore 持久化保存,并且每次项目启动时自动取localstore中获取相应的state 保存在redux中
import { save, load } from 'redux-localstorage-simple'
import user from './user/userSlice'
const PERSISTED_KEYS: string[] = ['user'] // localstore 的key
const store = configureStore({
reducer: {
user
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware({
serializableCheck: false
}).concat(save({ states: PERSISTED_KEYS })),
preloadedState: load({ states: PERSISTED_KEYS }),
})
export default store
export type AppState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
5.改造App.tsx 引入redux
import React from "react";
import Home from "@/pages/home";
import Login from "@/pages/login";
import {HashRouter,Route,Routes} from 'react-router-dom'
import {Provider} from "react-redux";
import store from '@/store'
const App = ()=>{
return (
<Provider store={store} >
<HashRouter>
<Routes>
<Route path="/" Component={Home}></Route>
<Route path="/login" Component={Login}></Route>
</Routes>
</HashRouter>
</Provider>
)
}
export default App;
6.编辑login.tsx 将用户的token保存到redux
import { connect } from 'react-redux';
import { setUserToken } from '@/store/user/userSlice’
...
onFinish= async (loginForm:Login.ReqLoginForm)=>{
//提交
this.setState({loading:true})
// 要这么使用,别忘记使用connect 注入
let {setUserToken} = this.props
setUserToken({ token: 'helloworld_test_token' })
this.props.navigate('/');
}
...
const mapDispatchToProps = {setUserToken}
// 将redux中的setUserToken 方法注入到props中
export default withNavigation(connect(null, mapDispatchToProps)(Login))
7.在页面上看看效果
至此,redux的引入就已经完成了
三、React-route 优化
使用配置文件配置路由以及使用路由守卫根据token判断是否可以登录home页面
- 创建routes目录以及index.tsx 配置入口文件
cd src
mkdir routes
cd routes
touch index.tsx
mkdir utils
touch routerGuards.tsx
- 编辑路由入口配置/routes/index.tsx
import Home from '@/pages/home'
import Login from '@/pages/login'
import { Navigate, useRoutes } from "react-router-dom";
export interface MetaProps {
keepAlive?: boolean;
requiresAuth?: boolean;
title: string;
key?: string;
}
export interface RouteObject {
meta?: MetaProps;
element?: React.ReactNode;
path?: string;
children?: RouteObject[];
}
export const rootRouter:RouteObject[]=[
{
path:"/",
element:<Navigate to="/home"/>
},
{
path:"/login",
element:<Login/>,
meta:{
requiresAuth:false,
title:"登录页",
key:"login"
}
},
{
path:"/home",
element:<Home/>,
meta:{
requiresAuth:true,
title:"主页",
key:"home"
}
}
]
const Router = () => {
const routes = useRoutes(rootRouter);
return routes;
};
export default Router;
- 创建路由守卫组件
import {useLocation, Navigate} from "react-router-dom";
import {rootRouter} from "@/routes";
import store from "@/store";
import { RouteObject } from "@/routes";
/**
* @description 递归查询对应的路由
* @param {String} path 当前访问地址
* @param {Array} routes 路由列表
* @returns array
*/
export const searchRoute = (path: string, routes: RouteObject[] = []): RouteObject => {
let result: RouteObject = {};
for (let item of routes) {
if (item.path === path) return item;
if (item.children) {
const res = searchRoute(path, item.children);
if (Object.keys(res).length) result = res;
}
}
return result;
};
/**
* @description 路由守卫组件
* */
const RouterGuards = (props: { children: JSX.Element }) => {
const {pathname} = useLocation();
const route = searchRoute(pathname, rootRouter);
// * 判断当前路由是否需要访问权限(不需要权限直接放行)
if (!route.meta?.requiresAuth) return props.children;
const token:string = store.getState().user.token;
console.log(token)
if (!token) return <Navigate to="/login" replace/>
return props.children;
}
export default RouterGuards;
- 改造App.tsx 主组件
import React from "react";
import Home from "@/pages/home";
import Login from "@/pages/login";
import {HashRouter,Route,Routes} from 'react-router-dom'
import {Provider} from "react-redux";
import store from '@/store'
import RouterGuards from "./routes/utils/routerGuards";
import Router from "@/routes";
const App = ()=>{
return (
<Provider store={store} >
<HashRouter>
<RouterGuards>
<Router/>
</RouterGuards>
</HashRouter>
</Provider>
)
}
export default App;
自此,已经完成了redux的引入以及react-route的可配置以及配合redux做路由守卫,在你访问http://localhost:8080/ 时如果没有登录过,会自动跳到login页面,登录后就会自动等路home页面