当前位置: 首页 > news >正文

react+redux+toolkit来实现公共数据的处理-对比vuex

前言:

        在react中处理公共数据有很多种方法,我们这里来说一说用 react+redux+toolkit 来实现公共数据的处理。

功能对比 redux与Vuex

功能VuexRedux Toolkit
状态定义stateinitialState
同步修改mutationsreducers
异步操作actionscreateAsyncThunk + extraReducers
模块化modules多个 slices + combineReducers
派生状态getters自定义 selector hooks
组件绑定mapStatemapActionsuseSelectoruseDispatch

安装

react-redux是状态管理工具,@reduxjs/toolkit是redux的工具包(官方大力支持,代码量更小,使用更方便)

npm i react-redux @reduxjs/toolkit

redux-persist 是数据持久化工具,可以存到本地

redux-persist-transform-encrypt  是数据加密的方法

npm i redux-persist redux-persist-transform-encrypt

使用:

1、main.jsx中注册下

import { createRoot } from 'react-dom/client'import App from './App.jsx'// 导入合并好的stores
import stores from './stores'// 导入reduxProvider组件传递store
import { Provider } from 'react-redux'createRoot(document.getElementById('root')).render(//使用redux的元素包起来,也可以放app.jsx中<Provider store={stores}><App /></Provider>
)

2、stores中,注册多个文件

类似vuex中得modules

index.js,可以引入多个,然后通过reducer来合并

import { configureStore } from "@reduxjs/toolkit";
import user from './user'
import shop from './shop'export default configureStore({reducer:{user,shop}
})

3、user.js

initialState 里面定义的变量跟vuex里面定义变量state一样,跟vue的data定义变量一样

reducers里面定义的方法函数跟vuex里面mutations一样

import { createSlice } from '@reduxjs/toolkit'// 创建userSlice切片,存储关于user的数据和修改user数据的方法action
const userSlice = createSlice({name: 'user-slice',// 每个切片的名字initialState: ({ // 定义数据user: {name: '张三',age: 18,gender: '男'}}),reducers: { // 定义方法集合setName: (state, action) => {state.user.name = action.payload},setAge: (state, action) => {state.user.age = action.payload},setGender: (state, action) => {state.user.gender = action.payload}}
})// 导出修改数据的方法,在组件中使用
export const { setName, setAge, setGender } = userSlice.actions
export default userSlice.reducer  // 导出切片

4、shop.js

跟上面user一样的写法, 加了个异步请求接口的方法,这里可以监听他的不同状态

等同于vuex的actions异步方法

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from 'axios';// 异步 action(类似 Vuex 的 actions)
export const fetchUser = createAsyncThunk('user/fetchUser', // action 类型前缀async (userId) => {const response = await axios.get(`/api/users/${userId}`);return response.data; // 返回值作为 action.payload}
);const shopSlice = createSlice({name: 'shop-slice',initialState: ({// 接口拿到的数据与loading状态等data: null, loading: false, error: nullshopList: [{name: 'xiaomi 15',price: '3999',id: 1}]}),reducers: ({// 同步-修改数组变量setName: (state, action) => {state.shopList[0].name = action.payload}}),extraReducers: (builder) => { // 处理异步 action 的不同阶段builder.addCase(fetchUser.pending, (state) => {state.loading = true;}).addCase(fetchUser.fulfilled, (state, action) => {state.data = action.payload;state.loading = false;}).addCase(fetchUser.rejected, (state, action) => {state.error = action.error.message;state.loading = false;});},
})export const { setName} = shopSlice.actionsexport default shopSlice.reducer

5、到这一步,可以直接在界面用了,比如demo.jsx中

dispatch(setAge() )   这就是调用同步方法 的使用,类似调用vuex里面的mutation方法

dispatch(fetchUser(12333))  调用异步方法的使用,类似调用vuex里面actions里面方法

import React from 'react'
import { useSelector, useDispatch } from 'react-redux' //固定使用
import { setAge } from '@/stores/user' //对应export 的对象 里面的函数方法名export default function Child() {const user = useSelector(state => state.user.user) //直接拿到定义的变量const dispatch = useDispatch()return (<div><h1>用户:{JSON.stringify(user)}</h1><button onClick={()=>dispatch(setAge(user.age+1))}>年龄加一</button></div>)
}
//异步调用接口
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';import { fetchUser } from '@/store/slices/user';
import { useUser } from '@/store/hooks';function UserProfile({ userId }) {const dispatch = useDispatch();const { data, loading, error } = useUser(); // 类似 mapStateuseEffect(() => {dispatch(fetchUser(userId)); // 类似 Vuex 的 actions}, [userId]);if (loading) return <div>Loading...</div>;if (error) return <div>Error: {error}</div>;return <div>Username: {data?.name}</div>;
}

6、正常项目中不会用这么简单方法,还可以定义类型,以及封装hook

比如类型的type

export interface RootState{key: stringpath: stringtitle: string
}

然后使用类型,以及发送上面定义变量的hook

import { useSelector } from 'react-redux';
import { RootState } from './type';// 封装自定义 selector hooks,统一在这个文件,界面用的时候统一从这个文件取,不用单独引入
export const useUser = () => useSelector((state: RootState) => state.user);
export const useCounter = () => useSelector((state: RootState) => state.counter);// 计算属性(类似 Vuex 的 getters)
export const useDoubleCount = () =>useSelector((state: RootState) => state.counter.value * 2);

7、第6步里面的类型定义是自定义用interface定义类型,也可以这样搞

在store/index里面
// 导出类型化的 hooks
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
然后再hook里面,接收他的定义好的类型,不用我们自定义去写
import type { RootState } from './index';

8、如果使用了数据持久化方法redux-persist

只需要在store/index文件里

// store/index.js
import { configureStore } from '@reduxjs/toolkit';import { persistStore, persistReducer } from 'redux-persist';import storage from 'redux-persist/lib/storage';
//import sessionStorage from 'redux-persist/lib/storage/session';import authReducer from './slices/authSlice';//分片,其它文件const persistConfig = {key: 'auth', //存储的keystorage, //默认是localStorage 
};
const persistedReducer = persistReducer(persistConfig, authReducer);//存起来export const store = configureStore({reducer: {auth: persistedReducer,},
});export const persistor = persistStore(store);//最后发送的时候,把缓存也带上

9、如果使用了加密encrypt插件

解密是自动完成的,注意一点,如果旧数据加密存在本地,新数据修改了key,那需要删除缓存内容

import { createStore } from 'redux';import { persistStore, persistReducer } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import encryptTransform from 'redux-persist-transform-encrypt';const persistConfig = {key: 'root',storage,transforms: [encryptTransform({secretKey: 'my-super-secret-key',// 加密keyonError: (err) => console.error('加密失败:', err),}),],
};

http://www.dtcms.com/a/327941.html

相关文章:

  • 深度学习日志及可视化过程
  • 【机器学习深度学习】归一化层
  • Java 编程每日一题:实现一个简易的 LRU 缓存
  • JavaSE:数据类型与变量
  • 13-docker的轻量级私有仓库之docker-registry
  • 网络安全第1—2天笔记
  • 【19】万集科技——万集科技嵌入式,校招 一面,二面,面试问答记录
  • 数据分析与可视化
  • Unity数据可视化图表插件XCharts
  • CS2服务器是何方神圣
  • 21.Linux HTTPS服务
  • imx6ull-驱动开发篇20——linux互斥体实验
  • mimiconda+vscode
  • Ceph的FileStore存储引擎详解
  • Ceph放置组(PG)详解
  • 石头剪刀布手势识别数据集-3,100 张图片 智能游戏系统 人机交互界面 教育娱乐应用 手势识别技术研究 实时视频分析 移动端AI应用
  • 8 反向引用
  • cartographer 后端优化流程
  • 渗透测试现已成为 CISO 战略的核心
  • @RequestMapping接收文件格式的形参(方法参数)
  • 数字孪生赋能全场景智慧化:从水利工厂到城市治理的综合解决方案
  • Akamai字符串解混淆
  • RSA各种密钥格式
  • C++ Rust与Go
  • 【taro react】 ---- 实现 RuiPaging 滚动到底部加载更多数据
  • 使用 Docker 一键部署火山引擎 Sandbox-Fusion,并开放 8182 端口
  • QT6 如何在Linux Wayland 桌面系统抓屏和分享屏幕
  • 力扣hot100 | 双指针 | 283. 移动零、11. 盛最多水的容器、42. 接雨水
  • 2787. 将一个数字表示成幂的和的方案数
  • 三维工厂设计软件 AutoCAD Plant 3D 安装图文教程