企业应用程序的最佳 React 状态管理工具
已发表: 2022-03-11企业级 React 应用程序的开发人员知道状态管理对于一致的最终用户体验的重要性。
然而,用户并不是唯一受状态管理影响的人。 React 开发人员创建和维护状态。 他们希望状态管理简单、可扩展和原子化。 React 通过引入 hooks 已经朝着这个方向发展。
当状态应该在许多组件之间共享时,可能会出现问题。 工程师必须找到适合他们需求的工具和库,同时满足企业级应用程序所需的高标准。
在本文中,我将分析和比较最流行的库,并选择最适合企业级应用程序状态管理的库。
内置 React 状态管理功能
React 有一个出色的工具,可以跨多个组件提供数据。 Context 的主要目标是避免螺旋钻。 我们的目标是获得一个易于使用的工具来管理企业应用程序中可能遇到的各种场景中的状态:频繁更新、重新设计、引入新功能等等。
虽然所有这些在理论上都可以通过 Context 实现,但它需要一个需要时间来设置、支持和优化的自定义解决方案。 Context 的唯一优点是它不依赖第三方库,但这不能超过维护这种方法的努力。
此外,React 团队成员 Sebastian Markbage 提到新的 Context API 不是针对高频更新构建和优化的,而是针对主题更新和身份验证管理等低频更新而构建和优化的。
检查现有库
GitHub 上有数十种状态管理工具(例如 Redux、MobX、Akita、Recoil 和 Zusand)。 但是,将它们中的每一个都考虑在内会导致无休止的研究和比较。 这就是为什么我根据受欢迎程度、使用情况和维护者将我的选择范围缩小到三个主要竞争对手。
为了明确比较,我将使用以下质量属性:
- 可用性
- 可维护性
- 表现
- 可测试性
- 可扩展性(在更大的状态下具有相同的性能)
- 可修改性
- 可重用性
- 生态系统(有多种辅助工具来扩展功能)
- 社区(有很多用户,他们的问题在网上得到解答)
- 可移植性(可以与 React 以外的库/框架一起使用)
还原
Redux 是 2015 年创建的状态容器。它之所以广受欢迎,是因为:
- 当它推出时,没有任何严肃的选择。
- 它提供了状态和动作之间的分离。
-
react-redux魔术启用了直接的状态连接。 - 该库的共同创建者是著名的 Facebook 开发人员和 React 核心团队成员 Dan Abramov。
您有一个全球存储数据所在的位置。 每当您需要更新 store 时,您都会派发一个动作到reducer 。 根据动作类型,reducer 以不可变的方式更新状态。
要将 Redux 与 React 一起使用,您需要通过react-redux为组件订阅商店更新。
Redux API 示例
Redux 在代码库中区别于其他工具的基本部分是切片。 它们包含所有的 action 和 reducer 逻辑。
代码沙盒
// slices/counter.js import { createSlice } from "@reduxjs/toolkit"; export const slice = createSlice({ name: "counter", initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1; }, decrement: (state) => { state.value -= 1; } } }); export const actions = slice.actions; export const reducer = slice.reducer; // store.js import { configureStore } from "@reduxjs/toolkit"; import { reducer as counterReducer } from "./slices/counter"; export default configureStore({ reducer: { counter: counterReducer } }); // index.js import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import App from './App' import store from './store' ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ) // App.js import React from "react"; import { useSelector, useDispatch } from "react-redux"; import { actions } from "./slices/counter"; const App = () => { const count = useSelector((state) => state.counter.value); const dispatch = useDispatch(); return ( <div> <div> <button onClick={() => dispatch(actions.increment())}>Increment</button> <span>{count}</span> <button onClick={() => dispatch(actions.decrement())}>Decrement</button> </div> </div> ); }; export default App;质量属性
- 可用性。 随着官方工具包的引入,Redux 变得非常简单。 您创建一个切片(初始状态、reducers 和操作的组合),将其传递给存储,并通过钩子在组件中访问它。
- 可维护性。 Redux 很简单。 它不需要深厚的知识来理解如何增强或修复某些东西。
- 性能。 Redux 的主要性能影响者是软件工程师。 Redux 是一个没有太多逻辑的简单工具。 如果您发现状态更新很慢,您可以按照官方指南来加快速度。
- 可测试性。 Redux 由纯函数(actions 和 reducers)组成,非常适合单元测试。 它还提供了编写集成测试的机制,其中 store、action 和 reducer 一起工作。
- 可扩展性。 默认情况下,Redux 有一个全局状态,因此很难扩展。 但是,有一个 redux-dynamic-modules 库可以创建模块化的 reducer 和中间件。
- 可修改性。 自定义 Redux 是一件轻而易举的事情,因为它支持中间件。
- 可重用性。 Redux 与框架无关,因此它非常擅长可重用性。
- 生态系统。 Redux 提供了一个由有用的附加组件、库和工具组成的庞大生态系统。
- 社区。 Redux 是我们比较中最古老的状态管理库,它已经积累了一个拥有重要知识库的大型社区。 Stack Overflow 上有约 30,000 个(约 19,000 个已回答)带有
redux标签的问题。 - 脉冲。 Redux 会定期更新和维护。
MobX
MobX 是另一个相对较旧的库,在 GitHub 上有 23,000 颗星。 它与 Redux 的不同之处在于它遵循 OOP 范式并使用 observables。 MobX 由 Michel Weststrate 创建,目前由一群开源爱好者在波士顿 Mendix 的帮助下维护。
在 MobX 中,您可以在构造函数中创建一个带有makeObservable调用的 JavaScript 类,该构造函数是您的可观察存储(如果您有适当的加载器,则可以使用@observable装饰器)。 然后声明类的属性(状态)和方法(动作和计算值)。 组件订阅此可观察存储以访问状态、计算值和操作。
MobX 的另一个基本特性是可变性。 如果您想避免副作用,它允许静默更新状态。
MobX API 示例
MobX 的一个独特功能是您可以创建几乎纯 ES6 的类,所有的魔法都隐藏在引擎盖下。 它需要较少的特定于库的代码来保持对逻辑的关注。
代码沙盒
// stores/counter.js import { makeAutoObservable } from "mobx"; class CounterStore { value = 0; constructor() { makeAutoObservable(this); } increment() { this.value += 1; } decrement() { this.value -= 1; } } export default CounterStore; // index.js import React from "react"; import ReactDOM from "react-dom"; import { Provider } from "mobx-react"; import App from "./App"; import CounterStore from "./stores/counter"; ReactDOM.render( <Provider counter={new CounterStore()}> <App /> </Provider>, document.getElementById("root") ); // App.js import React from "react"; import { inject, observer } from "mobx-react"; const App = inject((stores) => ({ counter: stores.counter }))( observer(({ counter }) => { return ( <div> <div> <button onClick={() => counter.increment()}>Increment</button> <span>{counter.value}</span> <button onClick={() => counter.decrement()}>Decrement</button> </div> </div> ); }) ); export default App;质量属性
- 可用性。 可观察存储是状态管理的单一入口点。 它使 MobX 的使用变得简单,因为您只有修改的地方。
- 可维护性。 这是一个相当大的缺点。 如果不了解 RxJS API,您将无法获得想要的结果。 在资质不佳的团队中使用 MobX 可能会导致状态不一致问题。
- 性能。 MobX 由独立的商店组成,使您能够订阅您需要的唯一商店。 这是非常有效的。
- 可测试性。 Observable 存储是简单的 JavaScript 对象,其中隐藏着反应性功能。 测试与任何其他 JavaScript 类相同。
- 可扩展性。 可观察存储在逻辑上被拆分; 扩展 MobX 没有任何困难。
- 可修改性。 MobX 允许创建具有修改行为的自定义 observables。 此外,还有一个概念叫做反应。 反应模型自动副作用。 这些东西让 MobX 非常可定制。
- 可重用性。 MobX 与框架无关,因此它非常擅长可重用性。
- 生态系统。 MobX 有数百个可用的扩展。
- 社区。 MobX 有很多忠实的粉丝。 Stack Overflow 上有约 1,600 个(约 1,000 个已回答)的带有
mobx标签的问题。 - 脉冲。 MobX 会定期更新和维护。
畏缩
Recoil 是一个相对较新的人,是 React 团队的最新创意。 它背后的基本思想是对缺少的 React 功能(如共享状态和派生数据)的简单实现。

您可能想知道为什么要为企业级项目审查实验库。 首先,Recoil 是目前 React 社区中讨论最多的话题之一。 其次,Recoil 得到 Facebook 的支持,并且已经在其一些应用程序中使用,这意味着它将在某个时候成为一个稳定的版本。 最后,这是一种在 React 中共享状态的全新方法,我敢肯定,即使 Recoil 已被弃用,也会有另一个工具遵循相同的路径。
Recoil 建立在两个术语之上: atom和selector 。 原子是一个共享状态片段。 一个组件可以订阅一个原子来获取/设置它的值。
正如您在图像中看到的,当值更改时,只有订阅的组件会重新渲染。 它使 Recoil 非常高效。
Recoil 开箱即用的另一个很棒的东西是选择器。 选择器是从原子或其他选择器聚合的值。 对于消费者来说,原子和选择器没有区别,他们只需要订阅一些反应部分并使用它。
每当一个原子/选择器改变时,使用它的选择器(即订阅它)都会被重新评估。
反冲 API 示例
Recoil 的代码与它的竞争对手相比有很大的不同。 它基于 React 钩子,并且更多地关注状态结构而不是改变这种状态。
代码沙盒
// atoms/counter.js import { atom } from "recoil"; const counterAtom = atom({ key: "counter", default: 0 }); export default counterAtom; // index.js import React from "react"; import ReactDOM from "react-dom"; import { RecoilRoot } from "recoil"; import App from "./App"; ReactDOM.render( <RecoilRoot> <App /> </RecoilRoot>, document.getElementById("root") ); // App.js import React from "react"; import { useRecoilState } from "recoil"; import counterAtom from "./atoms/counter"; const App = () => { const [count, setCount] = useRecoilState(counterAtom); return ( <div> <div> <button onClick={() => setCount(count + 1)}>Increment</button> <span>{count}</span> <button onClick={() => setCount(count - 1)}>Decrement</button> </div> </div> ); }; export default App;质量属性
- 可用性。 Recoil 是最容易使用的工具之一,因为它的工作方式类似于 React 中的
useState。 - 可维护性。 在 Recoil 中你所要做的就是在组件内部维护选择器和钩子——更多的价值,更少的样板。
- 性能。 Recoil 在 React 之外构建了一个状态树。 状态树使您能够获取和收听您需要的东西,而不是整个树的变化。 它在引擎盖下也得到了很好的优化。
- 可测试性。 Recoil 提供了一种测试其原子和选择器的机制。
- 可扩展性。 分裂成多个独立部分的状态使其成为可扩展性的良好参与者。
- 可修改性。 Recoil 只负责存储值及其聚合。 它没有数据流,因此可以轻松定制。
- 可重用性。 Recoil 依赖于 React。 它不能在其他地方重复使用。
- 生态系统。 Recoil 目前没有生态系统。
- 社区。 Recoil 太新鲜了,无法拥有一个大社区。 Stack Overflow 上有大约 70 个带有
recoiljs标签的问题。 - 脉冲。 Recoil 不经常更新(最近两次更新之间间隔了六个月)。 它在 GitHub 上也有很多未解决的问题。
选择正确的 React 状态管理工具
当涉及到企业级应用程序时,这些 React 全局状态管理库如何叠加?
Recoil 很年轻很新鲜,但目前没有社区和生态系统。 尽管 Facebook 正在开发它并且 API 看起来很有希望,但一个庞大的 React 应用程序不能依赖于社区支持薄弱的库。 此外,它是实验性的,使其更加不安全。 对于当今的 React 企业应用程序来说,这绝对不是一个好的选择,但值得关注。
MobX 和 Redux 不存在任何这些问题,市场上的大多数大玩家都在使用它们。 使它们彼此不同的是学习曲线。 MobX 需要对响应式编程有基本的了解。 如果参与项目的工程师不够熟练,应用程序最终可能会出现代码不一致、性能问题和增加的开发时间。 如果您的团队意识到反应性,MobX 是可以接受的,并且会满足您的需求。
Redux 也有一些问题,主要是关于可伸缩性和性能。 然而,与 MobX 不同的是,这些问题有经过验证的解决方案。
考虑到每一个优点和缺点,并考虑到我的个人经验,我推荐 Redux 作为 React 企业级应用程序的最佳选择。
