前言
我们的前端团队在一直深度使用 React
,从最早的 CRA ,到后来切换到 umijs ,从 1.x、2.x、3.x 再到现在的 4.x,其中有一点不变的,就是我们一直在使用基于 react-redux
思想的 dva 作为状态管理工具。
![](https://i-blog.csdnimg.cn/blog_migrate/048e85dff2fa83d7fa7a07822e4681be.png)
在状态共享这方面,不像 Vuex
,React
的官方并没有强力推荐某种封装方案,所以 React
的状态管理工具五花八门,百花齐放。其中就有:
- 做什么都要
dispatch
的redux
流派。包括:react-redux
、dva
、新星代表zustand
- 响应式流派
mobx
。以及新星代表valtio
,以及一个很有特点的库resso
- 原子状态流派。来自
facebook
开源的recoil
,以及新星代表jotai
- 完全体
hooks
流派。hox
、reto
、umijs@4 内置数据流
,包括Vue
官方推荐的新状态管理工具pinia
也是这个流派。
![](https://i-blog.csdnimg.cn/blog_migrate/024cf544f5ee795de79ae6df009953f6.png)
更为重要的一点是,传统的 MVC
模式,建议我们将视图层的逻辑层分离。而在 dva
中,页面即视图,effects
则被我们用于业务逻辑的编写。在这种思想的影响下,不论是简单还是复杂的页面,我们都习惯去创建一个 dva-model
,再加上 dispatch
都不是强依赖关系,久而久之, model
越来越臃肿,关系越来越难找,吐槽声越来越大。
随着技术不断发展,我们终归是要摆脱繁琐的 dva
,寻找一个新的状态管理工具,来减少我们这一块的代码量,保护我们的秀发。
所以经过了一系列的试点,我也来介绍一下各流派的优缺点和我个人的倾向。
我们需要什么样的状态管理工具
可能不需要?
我们阅读一些状态管理工具的文档时候,可能就会先被这样一篇文章甩在脸上:《你可能不需要状态管理工具》。
![](https://i-blog.csdnimg.cn/blog_migrate/ce9c81cfe00569bb50115730ad991826.png)
是的,不管是用起来繁琐的 dva
还是更为简洁的 recoil
,我们都不应该滥用状态管理工具。滥用只会给我们后面的维护和重构带来麻烦。
什么时候需要?
状态管理工具的作用,就是状态的共享,当共享状态发生变化,所有使用方都会触发重新渲染。所以,当然是状态需要被多方共享的时候,才需要使用状态管理工具了。比如:
- 当前登录的用户信息,姓名,角色,所属组织等
- 静态数据字典的缓存
- 需要 keep-alive 的数据(不一定用)
- 页面功能复杂,模块化后,模块之间仍需要共享的数据
请不要在【基础组件】中使用共享的状态,【基础组件】应该保持自身的独立性,做到高内聚
对状态管理工具的要求?
随着项目经验的积累,我总结出了状态管理工具应该满足的几个特性:
1.共享状态(基础),能够满足上面列举的几个场景;
2.共享业务逻辑,比如修改个人密码后需要退出并跳转至登录页(在菜单栏和个人中心都要调用,相同的逻辑不应该写多次);
3.共享状态模块化,即按不同业务逻辑,分开不同的文件创建共享状态。
4.再复杂一些的,涉及到共享状态之间的依赖,比如当我修改当前登录人的角色之后(比如从”项目经理“切换至”系统管理员“),记录菜单权限的状态也需要更新。
5.使用时,有清晰的依赖来源(import from
)。
6.对 TypeScript 支持良好,易编写。
主流状态管理工具都是怎么做的
传统流派 dva
![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e74f3f355d0744a0b60821aaea41fe89~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?%29%20![Pasted%20image%2020221010163018.png]%28https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/732eac92660b4186bdc74cf2b37f6abe~tplv-k3u1fbpfcp-zoom-in-crop-mark:4536:0:0:0.image?)
对比 dva
和 Vuex
不能说是非常相似,只能说是一模一样了。
dva
的state
和Vuex
的state
,用于存放需要共享的状态。dva
的redu