React18 + webpack5 + typescript (三)引入redux-toolkit 以及 优化react-route

一、安装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页面

  1. 创建routes目录以及index.tsx 配置入口文件
cd src
mkdir routes
cd routes
touch index.tsx
mkdir utils
touch routerGuards.tsx
  1. 编辑路由入口配置/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;


  1. 创建路由守卫组件
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;


  1. 改造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页面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值