react中使用Redux管理token以及token持久化

1.安装插件

javascript 复制代码
npm i @reduxjs/toolkit react-redux

2.新建状态管理文件

在src下新建store文件夹,store文件夹下新建模块文件夹(modules)和入口文件(index.js),modules文件夹下新建setToken.js文件

3.配置setToken.js

javascript 复制代码
import { createSlice } from "@reduxjs/toolkit";
import axios from 'axios'

const tokenStore = createSlice({
    name: 'setToken',
    initialState: {
        token: ''
    },
    reducers: {
        setToken(state, actions) {
            state.token = actions.payload
        }
    }
})

const { setToken } = tokenStore.actions;
const tokenStoreReducer = tokenStore.reducer;

// 异步请求
function login(data){
    return (dispatch)=>{
        axios.get('http://localhost:8888/token').then(res=>{
            dispatch(setToken(res.data))
        })
    }
}

export { setToken,login }
export default tokenStoreReducer

4.注册setToken模块

src/store/index.js

javascript 复制代码
// store/index.js该文件为状态管理的入口文件
// configureStore用于创建store实例
import { configureStore } from "@reduxjs/toolkit";

// 导入子模块reducer,用于注册子模块
import tokenStoreReducer from "./modules/setToken";

const store = configureStore({
    reducer:{ // 注册子模块的地方,可以注册多个子模块
        token:tokenStoreReducer
    }
})

export default store

5.挂载store

src/App.js

javascript 复制代码
// 该文件为主组件
import store from './store';
import { Provider } from 'react-redux';

import router from './router';
import { RouterProvider } from 'react-router-dom'

function App() {
  return (
    <RouterProvider router={router}>
      <Provider store={store}></Provider>
    </RouterProvider>
  );
}

export default App;

6.登录页面调用状态管理中的异步请求获取token

javascript 复制代码
import { Button, Checkbox, Form, Input, Card } from 'antd';
import './index.scss'
import { useState } from "react";
import { useNavigate } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { login } from '../../store/modules/setToken';


function LoginPage() {
    const navigate = useNavigate()
    const dispatch = useDispatch()
    const [formParams, setFormParams] = useState({
        username: 'kanno',
        password: '123456',
        remember: ''
    })
    const onFinish = async (values) => { // 提交按钮
        await dispatch(login(values)) // 点击提交时调用状态管理中的异步请求方法获取token
        navigate('/home') // 跳转到home页面
    };
    const onFinishFailed = (errorInfo) => {
        console.log('Failed:', errorInfo);
    };

    return (
        <div className="login">
            <Card style={{ width: 500 }}>
                <div className="title">登录</div>
                <Form
                    name="formParams"
                    style={{
                        width: '100%',
                    }}
                    initialValues={{
                        remember: true,
                    }}
                    onFinish={onFinish}
                    onFinishFailed={onFinishFailed}
                    autoComplete="off"
                >
                    <Form.Item
                        label="名称:"
                        name="username"
                        rules={[
                            {
                                required: true,
                                message: '请输入名称!',
                            },
                        ]}
                    >
                        <Input value={formParams.username} />
                    </Form.Item>

                    <Form.Item
                        label="密码:"
                        name="password"
                        rules={[
                            {
                                required: true,
                                message: '请输入密码!',
                            }
                        ]}
                    >
                        <Input.Password value={formParams.password} />
                    </Form.Item>

                    <Form.Item
                        name="remember"
                        valuePropName="checked"
                    >
                        <Checkbox>记住密码</Checkbox>
                    </Form.Item>

                    <div className="bottom">
                        <Button type="primary" htmlType="submit">
                            提交
                        </Button>
                    </div>
                </Form>
            </Card>
        </div>
    );
}

export default LoginPage;

6.说明

到这步就已经实现了将请求到的token存储在状态管理中,但是一旦刷新页面,存储在状态管理中的token就会丢失,因此,需要做token的持久化。

token持久化原理比较简单,就是在定义token状态变量的时候就将存储在本地存储的token赋值就行了。所以,在请求到token的时候就将token存储在状态管理和本地存储中,这样就算刷新存储在本地的token也不会丢失,就会在重新初始化的时候赋值到状态变量token中,从而达到token持久化的效果。

7.token持久化处理

在异步请求中存储到本地并且存储到状态管理中

src/store/modules/setToken.js 最终修改后的代码

javascript 复制代码
import { createSlice } from "@reduxjs/toolkit";
import axios from 'axios'

const tokenStore = createSlice({
    name: 'setToken',
    initialState: {
        token: localStorage.getItem('setToken')||'' // 从本地拿取token
    },
    reducers: {
        setToken(state, actions) {
            state.token = actions.payload;
            console.log("state.token",state.token);
        }
    }
})

const { setToken } = tokenStore.actions;
const tokenStoreReducer = tokenStore.reducer;

// 异步请求
function login(data){
    return (dispatch)=>{
        axios.get('http://localhost:8888/token').then(res=>{
            dispatch(setToken(res.data))
            localStorage.setItem('setToken',res.data); // 存储在本地
        })
    }
}

export { setToken,login }
export default tokenStoreReducer

8.最终效果

相关推荐
code_Bo13 分钟前
基于vxe-table进行二次封装
前端·javascript·vue.js
闭着眼睛学算法31 分钟前
【双机位A卷】华为OD笔试之【模拟】双机位A-新学校选址【Py/Java/C++/C/JS/Go六种语言】【欧弟算法】全网注释最详细分类最全的华子OD真题题解
java·c语言·javascript·c++·python·算法·华为od
晴殇i1 小时前
为什么现代 JavaScript 代码规范开始建议禁止使用 else ?
前端·javascript·前端框架
源力祁老师1 小时前
OWL与VUE3 的高级组件通信全解析
前端·javascript·vue.js
护国神蛙1 小时前
自动翻译插件中的智能字符串切割方案
前端·javascript·babel
PaytonD1 小时前
LoopBack 2 如何设置静态资源缓存时间
前端·javascript·node.js
snow@li1 小时前
d3.js:学习积累
开发语言·前端·javascript
天蓝色的鱼鱼2 小时前
Next.js 渲染模式全解析:如何正确选择客户端与服务端渲染
前端·react.js·next.js
一枚前端小能手2 小时前
🚀 巨型列表渲染卡顿?这几个优化技巧让你的页面丝滑如德芙
前端·javascript
酷柚易汛智推官2 小时前
Electron技术深度解析:跨平台桌面开发的利器与挑战
前端·javascript·electron