你们好,我是卡颂。缓存
在咱们React
进阶源码群里,除了React
外,状态管理是最常讨论的话题。markdown
诡异的是,有多个群友说过相似的话:工具
他的同事/组长/领导...让他把全部state都放在Redux/Mobx...里性能
他们以为不对,又不知道如何反驳。单元测试
今天咱们来聊聊Redux
、Mobx
等状态管理库和React
、Vue
等视图库之间的关系,但愿能解决以上困惑。测试
若是你在电梯里遇到大领导,他问你:spa
小x,大家最近在作什么功能?code
在电梯到达楼层前这短短2分钟,你该如何向大领导描述大家正在开发的功能呢?orm
我想你必定会介绍功能的大致逻辑,而不会聊功能里某个按钮的具体交互逻辑吧?开发
你会聊逻辑
,而不是交互
。由于逻辑
是最重要的。
接下来咱们经过一个小故事了解逻辑
与交互
的关系。
一天,老板让你开发文件上传功能。
开发过程其实就是处理文件上传这一领域相关的各类状态之间的关系(好比上传进度
、是否出错
...)。
这部分状态,咱们称为领域状态。
逻辑开发完后,你基于各类领域状态编写单元测试。
为了快速上线验证该功能是否有人用,你直接将其做为CLI
工具发布。
几天后,通过数据验证,发现功能很受欢迎。因而你选择React
做为视图库,基于以前的逻辑开发视图交互。
开发视图交互过程当中须要处理视图相关各类状态(好比loading显隐
、打开关闭状态
...)。
这部分状态,咱们称为视图状态。
可见,一款功能完备的产品包含领域状态与视图状态。前者是必须的,后者是可选的。
说回React
、Vue
这样的视图库。
因为大部分视图库以组件做为模块边界,因此很天然的,领域状态与视图状态被分割到不一样组件中,但他们被分割的方式是彻底不一样的。
举个例子,一个完整的应用能够划分为不少组件:
从视图状态角度来看这些组件:
对比上下两张图,组件1(黄色与绿色)大小一致,表明这是个交互逻辑自洽的纯组件(好比一个开关),他的交互逻辑不依赖其余组件。
除了组件1,更多组件须要与其余组件造成大小互补,这表明他们的交互逻辑互相影响。
好比组件5的长宽受组件二、组件六、组件8影响,可能表明:组件5是个提示框,他是否弹出受二、六、8影响。
咱们再从领域状态(蓝色部分)角度来看这些组件:
整个应用的逻辑分散在不一样组件中,可能组件1的didMount
回调中有一部分逻辑,组件3的useEffect
回调中有一部分逻辑。
因为组件5是个提示框,只有提示效果,因此他不包含应用运转所必需的逻辑(即领域状态)。
回到开篇,什么样的state
(状态)应该放在状态管理里?
对于视图状态:
状态自洽的组件本身管理状态(如组件1)
状态互相之间有影响的组件(如5与二、六、8)根据应用复杂度、组件间跨度决定
若是组件跨度比较近(如是兄弟关系),则公共状态能够提高到共同父组件。
若是组件跨度较远且应用不复杂,能够提高到共同的Context
中。
若是应用复杂,再考虑状态管理方案。
对于领域状态,因为其天生以碎片形式分布在不一样组件中,因此:
简单的小应用能够任其分布在组件中,或者提高到共同的Context
中
其余状况推荐用状态管理方案
甚至,对于领域状态中的子领域,能够在有状态管理方案的基础上再抽象出来单独处理。
好比对于服务端请求的数据这一领域状态,其性质更相似于缓存,在React
中可使用SWR
或React Query
处理。
本文咱们聊了状态的分类 —— 领域状态
与视图状态
,对于这两种状态根据其特性有不一样处理方案。
虽然一股脑将全部状态都交给Redux
处理不是不行,但势必对项目的可读性、性能、扩展性形成影响。
学完本文可以说服同事/组长/领导最好。若是对方执意要Redux
一把梭,对待这种执(憨)着(憨)的人,牢记四字箴言: