React--Redux④(RTK工具包)

RTK工具包

  • Redux Toolkit 是官方推荐用于编写 Redux 逻辑的工具包
  • 由于 Redux 的逻辑编写过于繁琐,并且代码通拆分在多个文件中,Redux Toolkit 旨在成为编写 Redux 逻辑的标准方式,从而解决代码繁琐的问题
  • 安装 Redux Toolkit
shell 复制代码
 npm i @reduxjs/toolkit

Redux Toolkit 的核心 API 主要如下:

  • configureStore: 包装 createStore 以提供简化的配置选项和良好的默认值,可以自动组合拆分的reducer,添加提供的任何 Redux 中间件(默认包含redux-thunk),并启用 Redux DevTools
  • createSlice: 接受 reducer 函数的对象、切片名称和初始状态值,自动生成切片 reducer,并带有相应的actions
  • createAsyncThunk: 接受一个 actionType 字符串和一个返回 Promise 的函数,生成一个基于该Promise 分派 actionTypethunk

基本使用

  • 原来的拆分模式是每个模块都有属于各自的 reduceractionCreators,使用 RTK 工具包对其重构
  • RTK 工具包官网: redux-toolkit.js.org/

通过 createSlice 创建切片,createSlice 主要包含以下参数和返回值

  • name: 标记切片的名词,会在 redux-devtool 中显示
  • initialState: 第一次初始化的值
  • reducers: 由函数组成的对象,相当于 reducer 函数,内部的函数类似每个 action 操作
  • 返回值: 一个对象,包含所有的 actionsreducer
javascript 复制代码
 // store/counter.js
 import { createSlice } from '@reduxjs/toolkit';
 ​
 const counterSlice = createSlice({
   name: 'counter',
   
   initialState: {
     num: 888
   },
   
   reducers: {
     addNum(state, action) {
       state.num += action.payload; // 这里做了优化,不需要返回新的state
     },
     subNum(state, action) {
       state.num -= action.payload;
     }
   }
 })
 ​
 export const { addNum, subNum } = counterSlice.actions
 export default counterSlice.reducer

使用 configureStore 创建 store 对象,常见参数如下:

  • reducer:slice 中的 reducer 组成一个对象传入
  • middleware: 可以使用参数,传入其他的中间件,默认集成 redux-thunkredux-devtool
  • devTools: 是否配置 devTools 工具,默认为 true
javascript 复制代码
 import { configureStore } from '@reduxjs/toolkit';
 import counterReducer from './modules/counter';
 ​
 const store = configureStore({
   reducer: {
     counter: counterReducer
   },
   devTools: true
 })
 ​
 export default store
  • 组件中使用还是通过 react-reduxProvider 共享和 connect 映射

异步操作(createAsyncThunk)

  • Redux Toolkit 默认已经集成了 Thunk 相关的功能:createAsyncThunk
javascript 复制代码
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import axios from 'axios';
 ​
 export const fetchBannersAction = createAsyncThunk('fetch/banners', async () => {
   const { data: { data } } = await axios.get(url);
   return data
 })

使用 createAsyncThunk 创建出来的 actiondispatch 时,存在三种状态:

  • pending: action 被发出,但还没有最终的结果
  • fulfilled: 成功获取到最终的结果
  • rejected: 执行过程中出现错误或者抛出异常
javascript 复制代码
 const homeSlice = createSlice({
   name: 'home',
   initialState: {
     banners: []
   },
   reducers: {},
   // 针对异步的action
   // extraReducers使用对象的写法在RTK2.0中准备弃用
   extraReducers: (builder) => {
     builder.addCase(fetchBannersAction.pending, (state, action) => {
       console.log(action.type); // fetch/banners/pending
     })
     .addCase(fetchBannersAction.fulfilled, (state, action) => {
       state.banners = action.payload.banner.list;
     })
     .addCase(fetchBannersAction.rejected, (state, action) => {
       console.log(action.type);
     })
   }
 })
  • 在不用 extraReducers 的情况下,使用普通的 reducers 也可改变 state 中的数据

createAsyncThunk 中的回调函数还有两个额外的参数:

  • extraInfo :额外信息,在调用 createAsyncThunk 返回的 Action 函数时传入的数据
  • store: 完整的 store
javascript 复制代码
 export const fetchBannersAction = createAsyncThunk('fetch/banners', async (extraInfo, store) => {
   const { data: { data } } = await axios.get('http://123.207.32.32:8000/home/multidata');
   store.dispatch(changeBanners(data.banner.list)) // 这里可以直接分发action
 })
 ​
 const homeSlice = createSlice({
   name: 'home',
   initialState: {
     banners: []
   },
   reducers: {
     changeBanners(state, action) {
       state.banners = action.payload
     }
   },
 })
 ​
 export const { changeBanners } = homeSlice.actions;
 export default homeSlice.reducer;
  • 像上面的做法也可以分发 action(本人比较喜欢),但还是使用官方推荐的 extraReducers

数据不可变(Immutable)

  • React 开发中,无论是类组件中的 state,还是 redux 中管理的 state,甚至在整个 JavaScript 编码过程中,数据的不可变性都是非常重要的,所以 React 经常会进行浅拷贝来完成某些操作

浅拷贝事实上也是存在问题:

  • 对过大的对象进行浅拷贝会造成性能的浪费
  • 浅拷贝后的对象,在作深层改变时,依然会对之前的对象产生影响
javascript 复制代码
 const friends = [
   { name: 'Jimmy' }
 ];
 ​
 const newFriend = [ ...friends ];
 newFriend[0].name = 'James' // 这里改变newFriend,friends里的对象也会被改变
  • 事实上 Redux Toolkit 底层使用了 immerjs 库来保证数据的不可变性
  • Immutable 对象的特点: 只要修改了对象,就会返回一个新对象,旧对象不会发生改变

为了节约内存使用新的算法:Persistent Data Structure(持久化数据结构)

  • 用一种数据结构来保存数据
  • 当数据被修改时会返回一个对象,但新对象会尽可能利用之前的数据结构,而不会对内存造成浪费
相关推荐
IT女孩儿1 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡2 小时前
commitlint校验git提交信息
前端
虾球xz3 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇3 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒3 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员3 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐3 小时前
前端图像处理(一)
前端
程序猿阿伟3 小时前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
疯狂的沙粒3 小时前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript
瑞雨溪3 小时前
AJAX的基本使用
前端·javascript·ajax