什么是状态管理:
状态管理工具的本质:
管理共享内存中的状态
共享内存 管理状态 页面通信 组件通信 刷新失效
React状态管理工具可以分为以下几类:
• react自带:Local State(props) 和 Context
• 单向数据流:Flux、Redux
• 双向数据绑定:Mobx
• 原子型状态管理:Recoil、Jotai
• 异步操作密集型:Rxjs
Local State(props):
顾名思义,就是组件级别的局部状态,比如:
上述的name就是一个简单的局部 local state,只在Hello这个组件中生效。当组件创建时初始化和生效,组件销毁时失效。
Context:
子页面和子页面之间的通信,可以使用Context
context存在的问题:
1、context相当于全局变量,难以追溯数据的变更情况
2、使用context的组件内部耦合度太高,不利于组件的复用和单元测试
3、会产生不必要的更新
4、context只能存储单一值,无法存储多个格子拥有消费者的值的集合
5、粒度不容易控制,不能细粒度地区分组件依赖了哪一个context
6、多个context会存在层层嵌套的问题
Redux:
Redux是由Flux演变而来的。
redux的三大原则:单一数据源、只有一个state、store中的state是只读的、使用纯函数来执行修改。
单一数据源:
在redux中,整个应用的全局State(再次注意是全局state),都会保存在一个store中,一个单一数据源 state tree 也简化了应用的调试和和监控;它也让你在开发中能将应用数据持久化到本地,从而加速开发周期。此外,有一些功能以前很难实现,比如“撤销/重做”,在单一数据源的原则下,使用Redux 实现将非常容易。
store中的state是只读的:
我们不能直接修改store中的state,store中的state是只读的。唯一能改变store中的state的方式就是通过action
使用纯函数来执行修改:
接受纯函数来接受aciton,该纯函数叫reducer,可以改变store中的state
因为Redux的上述特性,使得Redux可以做时间旅行。
时间旅行: 所谓的时间旅行从广义上来说无非就是三个动作:回到过去、进入未来、回到现在,让应用程序切换到任意时间的状态。
适用场景:
因此,如果复杂的场景,特别是存在页面组件间复杂的通信的场景非常适合用Redux来管理状态。 Redux 比较适合用于大型 web 项目,尤其是一些交互足够复杂、组件通信频繁的场景,状态可预测和回溯是非常有价值的。还有一种场景,比如需要事故重现,这种定义和上报事故异常和重现的场景,Redux也很有意义。
Redux的缺点也很明显,首先为了实现纯函数的Reducer, Redux必须处理各种各样的副作用,需要引入一系列的副作用中间件,加重的心智负担,此外Action,Dispatch,Reducer的模式需要写过多的样版代码,虽然通过React hooks 和 Redux toolkit可以减少一定的样板代码,但是复杂度还是摆在哪里。因此中小项目,也不太推荐使用Redux,可能Context或者React hooks中的useReducer就能满足你的需求。
Mobx:
它通过透明的函数响应式编程使得状态管理变得简单和可扩展,Mobx 跟 vue的设计比较相似,是一个响应式的状态管理库。Mobx 借助于装饰器的实现,使得代码更加简洁易懂。由于使用了可观察对象,所以Mobx 可以做到直接修改状态,而不必像 Redux一样编写繁琐的 actions 和 reducers
适用场景:
Mobx 的优势在于上手简单,可以直接修改状态,不需要编写繁琐的 Action 和 Reducer, 也不需要引入各种复杂的中间件,局部精确更新,免去了粒度控制烦恼,自始至终一份引用,不需要 immutable,也没有复制对象的额外开销。
因此前端数据流不太复杂的情况,推荐使用Mobx,因为更加清晰,也便于维护。
但是正是因为 Mobx 的灵活,Mobx 的代码风格很难统一。
不过 Mobx 是不能实现时间旅行和回潮的,因此不太适合前端数据流比较复杂的场景,此外,随着React hooks, 比如useReducer 等的,以及React自身的原子型状态管理工具Recoil。 Mobx的使用场景会被进一步压缩,目前的项目中使用Mobx的场景已经越来越小。
Recoil:
Recoil一定程度上解决了 Local State 和 Context 的局限性,且能够兼容React的新特性,比如Concurrent模式等。
解决的问题:
• 组件间的状态共享只能通过state提升至它们的公共祖先来实现,但这样做可能导致重新渲染一颗巨大组件树。
• Context只能存储单一值,无法存储多个各自拥有消费者的值的集合
Recoil 更加地具有原子性,比如在Recoil的状态都是Atom,可以进行任意组合。
Recoil 的核心,就是Atom原子状态,一集通过Atom原子状态可以派生出衍生状态Selector
Recoil主要特点,就是较为官方,提供了与 Concurrent 模式及其他 React 新特性兼容的可能性,主打的是性能。此外因为其原子性的特点,比较容易做到细粒度的状态控制。也能跟Redux实现状态回潮,相比较Redux而言,还有一个特点就是理解起来没有很复杂,不需要写很多样板代码等。
Recoil还有一个特点就是可以实现状态快照。比如填充首屏数据和数据状态回滚等。
Zustand:
Zustand是主打轻量级的状态管理工具,没有Redux那样臃肿的设计,也没有兼容React类组件的历史包袱,Zustand状态管理工具体积很小,因此很适合移动端的网页。