React状态管理工具如何选
这篇不是原创,到处找的资料
什么是状态
状态就是数据的变化。前端应用的核心问题就是管理状态,管理状态变化之前的通过视图或者其他方式触发的异步过程,管理状态变化之后的联动渲染和联动的逻辑执行
什么是状态管理
状态管理具体有两层含义:
- 状态变化之前的逻辑,一般是异步的
- 状态变化之后的联动处理,比如渲染视图或执行某段逻辑
比如 React 的 setState 不会马上修改状态,而是异步的批量的执行,把状态做一下合并。
比如 Redux 的 action 在修改全局 state 之前也是要经历中间件的处理的。
这些都是状态变化之前的异步过程的管理,是状态管理的第一层含义
再比如 React setState 修改了状态之后要触发视图的渲染和生命周期函数的执行,hooks 在依赖数组的状态变化之后也会重新执行。(vue 的 data 修改之后会重新渲染视图、执行 computed 和 watch 逻辑)
Redux 修改了全局状态之后要通知组件做渲染或者做其他逻辑的处理,Vuex、Mobx 等都是。
这些是状态变化之后的联动处理的管理,是状态管理的第二层含义
我们知道了什么是状态,什么是状态管理,那前端框架 Vue、React 和全局状态管理的库 Redux、Mobx、Vuex 都是怎么实现状态管理的呢
React 状态管理方案
方案对比
框架 | 原理 | 优点 | 缺点 |
---|---|---|---|
hooks context | 基于 react hook,开发者可实现内/外部存储 | 1. 使用简单 2. 不需要引用第三方库,体积最小 3. 支持存储全局状态,但在复杂应用中不推荐 4. 不依赖 react 上下文,可在组件外调用(外部存储的条件下) | 1. context value发生变化时,所有用到这个context的组件都会被重新渲染,基于 content 维护的模块越多,影响范围越大。 2.依赖 Context Provider 包裹你的应用程序,修改 store 无法在应用最顶层(App.tsx 层级)触发渲染 3. 受ui框架约束(react) 4. 依赖hooks调用 |
react-redux | Flux思想,发布订阅模式,遵从函数式编程,外部存储 | 1. 不依赖 react 上下文,可在组件外调用 2. 支持存储全局状态 3. redux 本身是一种通用的状态解决方案 | 1. 心智模型需要一些时间来理解,特别是当你不熟悉函数式编程的时候 2. 依赖 Context Provider 包裹你的应用程序,修改 store 无法在应用最顶层(App.tsx 层级)触发渲染 3.受 ui 框架约束(react) |
mobx | 观察者模式 + 数据截止,外部存储 | 1. 使用简单,上手门槛低 2. 不依赖 react 上下文,可在组件外调用 3. 支持存储全局状态 4.通用的状态解决方案 | 1.可变状态模型,某些情况下可能影响调试 2. 除了体积相对较大之外,笔者目前未感觉到较为明显的缺点,3.99M |
zustand | Flux思想,观察者模式,外部存储 | 1. 轻量,使用简单,上手门槛低 2. 不依赖 react 上下文,可在组件外调用 3. 支持存储全局状态 4. 通用的状态解决方案 | 1.框架本身不支持 computed 属性,但可基于 middleware 机制通过少量代码间接实现 computed ,或基于第三方库 zustand-computed 实现 |
jotai | 基于 react hook,内部存储 | 1. 使用简单 2. 组件颗粒度较细的情况下,jotai性能更好 3.支持存储全局状态 | 1. 依赖 react 上下文, 无法组件外调用,相对而言, zustand 在 react 环境外及全局可以更好地工作 2.受ui框架约束(react) |
recoil | 进阶版 jotai,基于 react hook + provider context,内部存储 | 相对于 jotai而言,会更重一些,但思想基本不变,拥有一些 jotai 未支持的特性及 api,如: 1.监听 store 变化 2. 针对 atom 的操作拥有更多的 api,编程上拥有更多的可能性,更加有趣 | 拥有 jotai 所有的缺点,且相对于 jotai 而言: 1.使用 recoil 需要 < RecoilRoot > 包裹应用程序 2. 编写 selector 会复杂一些 |
valtio | 基于数据劫持,外部存储 | 1. 使用简单,类mobx(类vue)的编程体验 2.支持存储全局状态 3.不依赖 react 上下文,可在组件外调用 4. 通用的状态解决方案 | 1.可变状态模型,某些情况下可能影响调试 2.目前笔者没发现其它特别大的缺点,个人猜测之所以star相对zustand较少,是因为 valtio 的数据双向绑定思想与 react 存在冲突。 |
文章参考:
https://zhuanlan.zhihu.com/p/394106764
https://fe.azhubaby.com/React/生态/状态管理.html
GPT:
1. React Context API
概述:Context API 是 React 自带的状态管理解决方案,适合于小范围状态共享。
优点:
- 无依赖:直接使用 React,不需要额外库。
- 简单易用:适合小型应用或共享简单状态。
- 内置 Hook:可与
useContext
钩子结合使用,方便获取上下文值。
缺点:
- 性能问题:频繁更新状态时,可能导致不必要的重新渲染。
- 缺乏中间件:不支持如 Redux 中的时间旅行和中间件。
适用场景:
- 小型应用,或主题、语言等简单状态共享。
2. Redux
概述:Redux 是一个强大的状态管理库,适合大型应用的集中式状态管理。
优点:
- 可预测性:状态的变化是可预测的,便于调试。
- 中间件支持:可以使用 Redux Thunk、Redux Saga 等中间件处理异步操作。
- 开发者工具:强大的调试工具支持。
缺点:
- 学习曲线陡峭:初学者需要时间理解 Redux 的概念(如 Reducer、Action)。
- 样板代码多:需要编写较多的代码,配置较复杂。
适用场景:
- 大型应用,需要管理复杂状态和多种异步操作。
3. MobX
概述:MobX 使用观察者模式,提供简单且高效的状态管理方案。
优点:
- 易于使用:自动依赖追踪,少量样板代码。
- 高效:仅在必要时更新组件,提高性能。
缺点:
- 灵活性带来的复杂性:状态管理可能变得不那么可预测,尤其在大型应用中。
- 社区支持相对较少:与 Redux 相比,文档和社区活跃度较低。
适用场景:
- 中型到大型应用,快速开发需求高的项目。
4. Recoil
概述:Recoil 是由 Facebook 开发的状态管理库,与 React 深度集成。
优点:
- 原子状态:状态以原子形式管理,支持更细粒度的状态更新。
- 简单直观:易于理解的 API,灵活性高。
缺点:
- 相对较新:文档和社区支持可能不足。
- 性能优化需求:复杂应用可能需要更多关注性能。
适用场景:
- 新项目,特别是需要灵活状态管理的中型应用。
5. Zustand
概述:Zustand 是一个轻量级的状态管理库,提供简单的 API。
优点:
- 轻量级:不依赖于复杂的上下文,简单易用。
- 无样板代码:创建 store 和使用状态都非常简单。
缺点:
- 功能较少:相对功能简单,适合基本的状态管理需求。
- 缺乏中间件:不支持复杂的异步操作管理。
适用场景:
- 小型到中型项目,快速原型开发。
6. Jotai
概述:Jotai 是一个基于原子状态的状态管理库,易于使用。
优点:
- 原子状态管理:允许创建独立的状态原子,灵活性高。
- 简单 API:与 React Hook 紧密集成,使用方便。
缺点:
- 新兴库:相对较新,文档和社区支持较少。
- 功能限制:对复杂状态管理的支持可能不如 Redux 强大。
适用场景:
- 小型到中型项目,尤其是需要灵活状态管理的场景。
总结
选择合适的状态管理工具时,需要考虑项目的复杂性、团队的熟悉度以及具体的需求。小型项目可以优先考虑 Context API 或轻量级库(如 Zustand 和 Jotai),而大型应用则可能更适合使用 Redux 或 MobX。Recoil 是一个灵活的选择,适合对原子状态有需求的中型项目。