使用「Redux Toolkit」简化redux操作
前言
使用redux-toolkit
能够简化创建redux
的流程和代码量,主要通过使用createReducer
和createSlice
这两个函数让我们轻松管理redux
的状态,同时在中间件中默认配置了thunk
,不需要额外安装redux-thunk
等中间件。
简介
RTK
致力于解决如下三个问题
- "配置一个 Redux store 过于复杂"
- "做任何 Redux 的事情我都需要添加很多包"
- "Redux 需要太多的样板代码"
RTK
包含主要如下的Api
configureStore
包装 createStore
以提供简化的配置选项和良好的默认预设。它可以自动组合你的切片 reducers,添加您提供的任何 Redux 中间件,默认情况下包含 redux-thunk
,并允许使用 Redux DevTools 扩展。
createReducer
为 case reducer 函数提供 action 类型的查找表,而不是编写switch语句。此外,它会自动使用immer
库来让您使用普通的可变代码编写更简单的 immutable 更新,例如 state.todos [3] .completed = true
。
createAction
为给定的 action type string 生成一个 action creator 函数。函数本身定义了 toString()
,因此它可以用来代替 type 常量。
createSlice
这个createSlice
函数,在我看来是RTK中的核心api,官方文档中对它的描述是这样的:该函数接收一个初始化state
对象,和一个reducer
对象,它可以将store以slice
的方式分割成为不同的部分,每个部分都会独立生成相对应的action
和state
对象。在99%的情况下,我们都不会直接使用createReducer
和createAction
,取而代之的就是createSlice
。
createAsyncThunk
用来处理异步操作的方法,对于使用RTK的项目来说,完成异步操作主要分三个步骤,createAsyncThunk
方法主要用来创建异步函数,创建完毕之后在reduce
中进行处理,最后在业务代码中用dispatch
进行调用,基本流程和标准的Redux并无二致。(需要注意的是,在createSlice
中,我们不可以用普通的reduce
处理异步函数,必须使用 extraReducers
来处理异步)
createEntityAdapter
生成一组可重用的 reducers 和 selectors,以管理存储中的规范化数据
createSelector
来自 Reselect 库,为了易用再导出。
使用
安装
yarn add @reduxjs/toolkit
configueStore 创建图书馆
//index.js
import { configureStore } from "@reduxjs/toolkit"
export default configureStore({
reducer: {
// 各个模块
},
})
configuleStore
我们可以比喻为一个图书馆,在图书馆建好之后,我们需要放入图书,但是也不能乱放,我们按照图书分类放置,而分类中每一类在redux
中我们称之为slice
切片
slice 图书分类
而slice
我们可以比喻为图书的分类,Slice Reducer切片 其实就是类似于vuex中的 module模块,也就是把图书按种类放在对应的书架上,方便放也方便找!
我们通过createSlice
创建切片
import { createSlice } from "@reduxjs/toolkit"
export const slice = createSlice({
name: "someOne",
initialState: {
character: "shy",
},
reducers: {
setActiveDate: (state, action) => {
state.character = action.payload
},
},
})
export const { setActiveDate } = slice.actions
export default slice.reducer
在这里我们创建了一个切片,里面的initalState
是初始值,但是还涉及到两个概念reducer
和action
Reducer 图书管理员
Reducer
我们可以理解为图书馆管理员,存放图书,借书,修改图书都需要经过它的手
Reducer
有以下几个特点:
-
仅使用
state
和action
参数计算新的状态值' -
禁止直接修改
state
。必须通过复制现有的state
并对复制的值进行更改的方式来做 不可变更新(immutable updates) 。 -
禁止任何异步逻辑、依赖随机值或导致其他“副作用”的代码
-
Reducer是一个纯函数
action 图书馆借书卡
action
在代码中表现为一个具有type
字段的javascript对象
const getHerInfo = {
type: 'CHARACTER'
}
const descripeHer = {
type: 'CHARACTER',
payload: 'so cool'
}
Reducer图书馆管理员 只能根据组件传入的 action借书卡 基于当前的图书执行指定操作
useSelector 图书馆电脑
通过图书馆电脑我们能查到我们的借书信息
React
组件使用 useSelector
钩子从 store 读取数据
选择器函数接收整个 state
对象,并且返回需要的部分数据
每当Redux store 更新时,选择器将重新运行,如果它们返回的数据发生更改,则组件将重新渲染
useDispatch
useDispatch
相当于我们把图书还给图书管理员Reducer
import { useDispatch } from "react-redux"
//...
const dispatch = useDispatch()
const setCharacter = (cha) => dispatch(descripeHer(cha))
onClick={() => {
setCharacter('so cool')
}}
immutable:不可变
不管是react
或者我们的redux
,都会提到这样一个关键词immutable
,指的是我们不应该直接去修改数据,需要把数据复制一份在去修改,如果react
判断到数据改变了,就会re-render,但是如果我们直接把数据修改了,他就无法判断数据的新旧了,导致一个初学者容易遇到的问题,数据修改了组件却没有重新渲染
从代码层面来说,js的数组和对象都属于引用类型,这样就导致我们没办法判断一个新数据与一个旧数据 是否不同,这一点在 react或者是vue的响应式 实现中都是容易踩坑的。
以下是官方文档中提到的不能在 Redux 中更改 state 几个原因:
- 它会导致 bug,例如 UI 未正确更新以显示最新值
- 更难理解状态更新的原因和方式
- 编写测试变得更加困难
- 它打破了正确使用“时间旅行调试”的能力
在使用
createSlice()这个api创建切片时,我们传入的参数reducers属性中使用的方法可以直接修改state,因为
createSlice` 内部使用了一个名为 Immer 的库,帮助我们将更新转换为不可变更新,这样就方便很多啦~
总结
如果工作中使用的是redux
,那我们应该会配上redux-toolkit
,感觉可以减少开发的负担,但是现在用的是mobx
,总之多了解一下其它的库对我们是比较有利的,下一篇文章大概会去深入了解下mobx.
转载自:https://juejin.cn/post/7085151613035216909