为了账号安全,请及时绑定邮箱和手机立即绑定

【九月打卡】第十九天 Redux-toolkit

标签:
redux

课程:React18 系统精讲

章节:Redux-toolkit

讲师:阿莱克斯刘

课程内容

【概念理解】什么是redux-toolkit

关于redux-toolkit,我们在本章开始的时候做了一点点基本的介绍,本节课,我们来深入剖析一下。

在深入研究源码之前,请同学们先打开redux-toolkit的官网 https://redux-toolkit.js.org/,我们先来简单了解一下什么是redux-toolkit,接下来的课程我都会使用redux-toolkit的简称RTK。

首先,我们看到在主页的副标题红,明确的写着这是official的、opinionated的、batteries的、以及efficient的工具。

  • Official 的意思就是说他是redux团队官方推出的插件,官办背景的背书质量以及后续的维护肯定是有保障的。

  • 第二个 Opinionated 的意思就是,他不仅是一个工具,而且还会提供一个更加简单的架构思想。比如, 合并action与reducer,再比如自动处理异步逻辑等等。

  • 第三个batteries,意思是会他会自带一系列官方推荐的工具集,方便我们的项目集成。

sXaNY4.png

  • 最后,efficient,就是高效的意思。关于这一点,我先放一点代码的对比图片,在完成本章后,同学们明显的看到使用RTK与传统redux的代码效率的区别。

sXadp9.png

学习前提

再次明确一下我们本章的学习前提,学习redux-toolkit,我们必须掌握redux以及react-redux的基本原理,还对这两个概念不理解的同学建议先回到前面几张复习一下。

sXaGwT.png

源码解读

接下来,我将会带着同学们解读源码,我现在打开的是RTK的代码库。研究源码,第一件事情就是要先研究一下他的依赖项目。请打开package.json.

package.json.

在depanency这个属性下面,我们可以看到RTK需要4个依赖。

  • redux:我们从最简单的开始,当然,RTK需要安装redux才能工作,什么意思呢?就是说如果我们的项目安装了RTK,就不需要重复安装redux了。但是,如果同学们观察的足够仔细,就会发现他的依赖项并不包含react-redux。所以说,redux-toolkit并不只是给react项目使用的,你要是愿意,也可以在vue、或者angular、甚至是jQuery项目中使用。也就是说,如果你想再redux-toolkit项目中使用react-redux,那么你也得手动安装

  • 第二个依赖,RTK自带了redux-thunk来处理异步逻辑,thunk在RTK项目中是默认启动的,请注意,我这里说的是默认启动,也就是说你自己在开发过程中也可以关闭或者是使用redux-sage等其他异步处理中间件来替代thunk。

  • 第三个reselect,这也是一个比较流行的redux插件,他可以帮助我们在使用state selector的时候记住当前的状态,这样就可以防止你的组件在不需要的时候被无意识的渲染了。这个插件我还是比较喜欢的,平时工作中也会使用,不过我们的课程属于react入门,所以就暂时不深入讲解了。有机会我也做一个补充材料,给同学们阅读。

  • 最后一个,也是最难理解的,就是immer。这个immer是一个非常有意思的插件,他允许我们把state从immutabe转化为mutable,也就是说,我们可以在reducer中直接更改state数据了。第一次听到这个思路的时候,理性告诉我这是不对的,因为这样就等于在违反reducer函数式编程的理念。而在redux的官方文档中,Immutable Update Patterns 明确说明reudx的一个核心原则就是Immutable ,我们不能直接更新store,而是要通过数据替换来解决更新问题。

但是,在亲身体验过immer以后,我觉得“真香”。。而且,如果同学们继续往下看文档,我们又会看到一个Immutable Update Utility Libraries这个自然段, 这里又是另一番描述,告诉我们官方支持使用immer来直接修改state,所以对于这种前后矛盾的说法,我也不知道该做什么评论。

那么,这个问题就留给同学们自己思考,不管怎么样、不管文档说什么,我们都一定要保持自己的独立思考习惯,我们可以继续使用immutable状态state,也可以使用immer来直接更新state,这完全取决于自己对代码、对项目、对架构的理解。

而我也将会在接下来的课程中介绍使用immer和不使用immer的两种方式,请同学们自己来做判断。

Api 详解

现在,请同学们回到RTK的官方文档,请同学们点击右上角的API按钮,我们先来学习一下他的api文档,在左边的api导航栏中,我们可以看到这里列出了RTK所有的api,这里总共有10个主要的api加上一些其他不重要的api,我们将会在接下来的代码实战中逐个研究。不过,有一点值得高兴的是,RTK所有的文档都是typescript写的,这与我们的项目契合度非常高。

在所有的api中,有两个api特别值得我们关注,不是createReducer、不是createAction,而是createSlice和configStore。

createReducer

不过,重要的事项留在后面,我们先来看看createReducer。文档的第一个例子很眼熟,这就是普通redux架构中的reducer。reducer很简单,就是couterReducer函数接受两个参数,state和action,然后返回新的state。

而对于RTK项目来说,我们有Reducer有两种创建方法,第一种是"Builder Callback" Notation,使用回调构建对象。

sXaJTU.png

另一种是"Map Object" Notation,使用映射对象。我更建议同学们在开发过程中使用第二种方法,映射对象的方法,因为我认为这种书写方式更直观,更容易理解。

sXaUfJ.png

所以,我们couterReducer的创建方式非常简单,如下图所以,直接使用createReducer函数,第一个参数是initialState,也就是初始化state,而第二个参数就是action与reducer的混合体。

sXatkF.png

在使用createReducer以后,我们不需要额外定义action类型了,reducer中也可以免去switch语句。当reducer和action合并以后,没有了模版代码,我们的代码量至少能够减少30%以上。

createAction

而如果我们非要写清楚action,那么你也可以使用createAction函数,比如这样

sXaVw8.png

通过这种方式,我们就可以向外以对象的形式来输出action了。我们也可以稍微看一眼文档。文档很简单,几乎不用解释了吧,就是把我们之前写的各种 action creator封装起来,加个范型定义一下payload类型而已。

sXakOP.png

sXaZTS.png

sXauWj.png

createSlice

不过,在99%的情况下,我们都不会直接使用createAction和createReducer这两个函数,取而代之的是使用createSlice。

sXaQln.png

createSlice绝对是RTK核心中的核心,我们先来看看文档是怎么说的。

什么意思呢?createSlice函数接受初始化state和对象化映射后的reducer,可以将store以切片slice的方式分割成为不同的部分,每个部分都会独立、而且自动生成相对应的action与state对象。

我们直接来看一下代码示例:

  • createSlice函数的参数是个对象,

  • 第一个字段是slice名称,相当于分割store以后的命名空间。

  • 第二个字段是initialState,就是数据初始化。因为initialState是redux数据启动的必要前提,而在传统的reducer中,我们必须要在参数上使用等号来定义initialState,有时候程序员会忘记写上initialState,这时候程序就会报错。现在,在RTK中我们直接使用在对象中强制定义了initialState,这样就可以完美避免state数据悬空的问题。

sXa8mV.png

  • 第三个字段是reducer,但是这是一个特殊的reducer,因为他把action和reducer结合在一起了,这与我们刚刚介绍过的createReducer是一样的。

sXamFg.png

不过,不知道同学们有没有发现一个细节,就是在reducer的case中,我们可以看到state实际上是被直接修改了的。这是怎么回事?为什么可以直接修改state,而不是重建state?直接修改state是否违反了immutable的原则呢?

其实,这就是刚刚给同学们介绍的immer的神奇所在了,因为RTK自动加载了immer,所以当我们在直接修改state的时候,immer实际上是在最底层帮我们重建state对象的。所以,从原理上来说这样的修改是有效的,而且并不违背immutable的原则。只不过是我自己对这种可变更state的思路有一点抵触情绪而已。关于state应该是immutable还是mutable这个问题,欢迎同学们加入课程的讨论群,我们一起一边讨论一边学习。

不过,好像这样看起来,这个createSlice函数也没什么了不起的,不就是把reducer和action捆绑在一起了吗?

好的,请同学们把页面往下拉,找到example,我们来仔细研究一下。大体上来说,这个案例与刚刚我们讲解的差不多,但是有两个地方值得我们注意。

  • 第一个,是couter slice中的multiply乘法reducer,它也包含两个字段,第一个是reducer本身,就是multiply乘法的处理函数,

只不过多了一个“extraReducers”字段,extraReducers是用来处理js模块环形引用问题的,我们先暂时跳过。

sXaEef.png

sXanYQ.png

sXaMSs.png

案例中有两个slice,一个conter,一个user。我们还是会使用combineReducers函数把两个reducer合并起来,不过,请注意,reducer是从slice中来的。然后使用createStore来创建store。

sXalyq.png

然后,神奇的事情就发生了,当使用dispatch的时候,我们可以通过对象的形式,直接访问action,而action是有reducer自动生成的,他所对应的是不同的case的action creator。这样的好处是什么呢?好处就是,我们把action干掉了,代码看起来干净整齐了很多,同时,我们也不需要再使用switch语句来判断action类型了,不仅杜绝模版简化了代码,而且还从源头上解决了string类型action出错的可能性,

值得注意的是倒数第四行代码,console log打印了couter的action对象,结果我们看到的输出是一个字符串,这个字符串是RTK自动生成的,前半段是slice名称,就相当于是命名空间,而后半对所对应的就是reducer的对象的名称,也是action类型的名称。

sXa1O0.png

当然,以上这一切都只是使用了redux-toolkit以后的语法糖而已。redux-toolkit与react-redux一样,使用特定的语法结构来在更高的层次上对redux的架构进行了封装。但落实到原理级别,还是离不开action、reducer、state、middleware这些基本组件。所以,想熟练使用redux-toolkit,能够掌握redux的基本原理是绝对的前提条件。

configureStore

最后,我们来看一下configureStore。ok,一开篇就开始自卖自夸了,介绍说configStore是一个非常友好的创建redux store的方式,也就是说,我们可以通过configureStore来代替redux原生的createStore函数了。

configStore会带有一些预先定义好的参数,而参数也是以对象的形式传递进来的。

  • reducer:就不用多说了吧,定义了store的state数据的初始化与变化过程

  • Middleware:中间件,Middleware,值得说道一下。这里会默认传入两个中间件,一个是react-thunk,另一个就是immer,我们可以通过getDefaultMiddleware函数取得默认中间件。

  • devTools:开启以后,我们每次dispatch action,都会在console中打印action和state的数据,我们会在接下来代码中尝试一下这个选项。

  • preloadedState: preloadedState,enhancers 与原生reudx 的createstore用法一样,preloadedState用来设置初始化state,而且可以覆盖reducer中的initialState

  • Enhancers:就是提供另一个途径来添加中间件。最后这两个字段用处比较少,可以不需要太关注。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消