作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.< / div >< / div >
Teimur Gasanov
< / div >

Teimur Gasanov

< / div >
验证专家 在工程< / div >< / div >< / div >< / div >

Teimur是反应的导师,也是Toptal核心团队的高级前端工程师.

< / div >< / div >

专业知识

反应.js回来的< / div >< / div >

以前在

Klarna< / div >< / div >< / div >< / div >< / div >< / div >< / div >< / div >< / div >
< / div >
< / div >
< / div >< / div >分享< / div >< / div >< / div >
< div >

编者注:本文由我们的编辑团队于2022年10月17日更新. 它已被修改为使用嵌入式代码演示, 参考最近的数据, 并与我们目前的编辑标准保持一致.

企业级反应应用程序的开发人员知道状态管理对于一致的最终用户体验是多么重要.

然而,用户并不是唯一受状态管理影响的人. 开发人员反应 创建和维护状态. 他们希望状态管理简单、可扩展和原子化. 反应已经朝着这个方向发展了 引入钩子.

当状态应该在许多组件之间共享时,可能会出现问题. 工程师必须找到适合他们需要的工具和库, 同时满足企业级应用程序所需的高标准.

在本文中, 我分析和比较了最流行的库,并选择了最适合的一个 反应状态管理 在企业级应用程序中.

内置的反应状态管理功能

反应具有跨多个组件提供数据的优秀工具. 的主要目标 上下文 是为了避免螺旋桨钻井. 我们的目标是获得一个易于使用的工具来管理企业应用程序中可能遇到的各种场景中的状态:频繁的更新, 重新设计, 新特性的引入, 等等.......

上下文的唯一优点是它不依赖于第三方库, 但这并不能抵消维持这种方法所付出的努力.

推特< / div >

虽然所有这些在理论上都是可行的, 它需要一个定制的解决方案,需要时间来设置, 支持, 和优化. 上下文的唯一优点是它不依赖于第三方库, 但这并不能抵消维持这种方法所付出的努力.

作为反应团队成员 Sebastian Markbage提到过, 上下文API不是为高频更新而构建和优化的,而是为低频更新而构建和优化的,比如主题更新和身份验证管理.

检查现有的反应状态管理库

在GitHub上有几十个状态管理工具.g., 回来的, MobX, 秋田犬, 反冲, Zust和). 然而,考虑到每一个因素都会导致无休止的研究和比较. 这就是为什么我把选择范围缩小到三个主要竞争对手的原因 受欢迎程度, 使用, 维护人员.

为了更明确地进行比较,我使用了以下质量属性:

  • 可用性
  • 可维护性
  • 表演
  • 可测试性
  • 可伸缩性(在更大的状态下以相同的性能工作)
  • 可修改性
  • 可重用性
  • 生态系统(有各种辅助工具来扩展功能)
  • 社区(有很多用户,他们的问题在网上得到回答)
  • 可移植性(可与反应以外的库/框架一起使用)

回来的

回来的 状态容器是在2015年创建的吗. 它之所以广受欢迎,是因为:

  • 当它推出时,并没有真正的替代方案.
  • 它提供了状态和动作之间的分离.
  • 反应-redux魔术支持直接的状态连接.
  • 回来的库的共同创建者是著名的Facebook开发者和反应核心团队成员Dan Abramov.

动画显示状态和动作的进展,从和到减速器,使用回来的.
< / div >

你有 一个全球性的商店 您的数据存放在哪里. 无论何时需要更新存储,都可以调度 一个动作 这就是 减速机的. 根据操作类型的不同,reducer会以不可变的方式更新状态.

要在反应中使用回来的,您需要通过反应 - 回来的将组件订阅到存储更新.

回来的 API示例

切片是回来的代码库的基本部分,它区别于其他工具. 切片包含操作和reducer的所有逻辑.

/ /片/计数器.js
从“@reduxjs/toolkit”中导入{createSlice};

导出const切片= createSlice({
  名称:“计数器”,
  initialState: {
    值:0
  },
  还原剂:{
    increment: (状态) => {
      状态.Value += 1;
    },
    decrement: (状态) => {
      状态.Value -= 1;
    }
  }
});

导出const 行动 = slice.行动;
导出const reducer = slice.减速机;


/ /存储.js
从“@reduxjs/toolkit”中导入{configureStore};
导入{reducer作为计数器Reducer}./片/计数器”;

导出默认配置恢复({
  减速机:{
    柜台:计数器Reducer
  }
});


/ /索引.js
从“反应”中导入反应
从“react-dom”中导入反应DOM
从“react-redux”中导入{Provider}
导入应用程序./应用程序
从'导入存储'./存储的

反应DOM.呈现(
  
    
  ,
  文档.getElementById(根)
)


/ /应用程序.js
从“反应”导入反应;
从“react-redux”中导入{useSelector, useDispatch};
导入{行动}./片/计数器”;

const App = () => {
  const count = useSelector((状态) => 状态.计数器.值);
  const dispatch = useDispatch();

  回报(
    
{count}
); }; 导出默认App;

质量属性

  • 可用性. 回来的变得非常简单 官方工具包包. 您创建了一个切片(初始状态的组合), 异径接头, 和行为), 把它递给商店, 并通过钩子在组件中访问它. RTK Query的加入使回来的 Toolkit成为可能 更有用 通过处理标准数据查询.
  • 可维护性. 回来的很简单. 它不需要深入的知识来理解如何增强或修复某些东西.
  • 表演. 回来的的主要性能影响因素是 软件工程师. 回来的是一个没有太多逻辑的简单工具. 如果您看到状态更新缓慢,则可以跟踪 官方指导方针 让它们更快.
  • 可测试性. 回来的由纯函数(操作和reducer)组成,这使得它非常适合单元测试. 它还提供 的机制 编写存储、操作和reducer一起工作的集成测试.
  • 可伸缩性. 默认情况下,回来的只有一个全局状态,这使得它难以扩展. 然而,图书馆 redux-dynamic-modules 支持创建模块化reducer和中间件.
  • 可修改性. 定制回来的是一件毫不费力的事情,因为它支持 中间件.
  • 可重用性. 回来的与框架无关,因此它在可重用性方面非常出色.
  • 生态系统. 回来的了 巨大的生态系统 有用的附加组件、库和工具.
  • 社区. 回来的, 在我们的比较中最古老的状态管理库, 已经积累了一个拥有重要知识库的大型社区. 带有redux标签的问题有34000个(回答了26000个) 堆栈溢出.
  • 脉冲. 回来的仍然定期更新和维护, 但随着项目的成熟,开发速度总体上有所放缓

MobX

MobX 是另一个相对较老的库,在GitHub上有~25,800颗星. 它与回来的的不同之处在于它遵循OOP范式并使用可观察对象. MobX是由 米歇尔Weststrate 它目前由一群开源爱好者在波士顿的帮助下维护 Mendix.

使用MobX描述状态管理的图表, 从动作到可观察状态和计算值再到副作用.
< / div >

在MobX, 在构造函数中创建一个带有makeObservable调用的JavaScript类 可观察到的商店 (如果你有合适的加载器,你可以使用@observable装饰器). 然后声明属性(状态)和方法(行动计算的值)的班级. 组件订阅这个可观察存储来访问状态, 计算值, 和行动.

MobX的另一个重要特性是 可变性. 它允许在您想要避免副作用的情况下静默地更新状态.

MobX API示例

MobX的一个独特之处在于,您可以创建几乎纯ES6类,其中隐藏了所有的魔力. 它需要较少的特定于库的代码,以便将注意力集中在逻辑上.

/ /存储/计数器.js
从“mobx”中导入{makeautooobservable};

类CounterStore {
  值= 0;

  构造函数(){
    makeAutoObservable(这个);
  }

  增加(){
    这.Value += 1;
  }

  减量(){
    这.Value -= 1;
  }
}

导出默认的CounterStore;


/ /索引.js
从“反应”导入反应;
从“react-dom”中导入反应DOM;
从“mobx-react”中导入{Provider};
导入App./应用程序”;
从“./商店/计数器”;

反应DOM.呈现(
  
    
  ,
  文档.getElementById(“根”)
);


/ /应用程序.js
从“反应”导入反应;
从mobx-react中导入{inject, observer};

const App = inject((stores) => ({ 计数器: stores.柜台}))(
  observer(({ 计数器 }) => {
    回报(
      
{计数器.value}
); }) ); 导出默认App;

质量属性

  • 可用性. 可观察存储是状态管理的单一入口点. 它使MobX的使用变得简单,因为您只有一个地方可以修改.
  • 可维护性. 这是一个相当大的缺点. 如果不了解RxJS API,您将无法获得期望的结果. 在不合格的团队中使用MobX可能会导致状态不一致的问题.
  • 表演. MobX由独立的商店组成,使您能够订阅您需要的唯一商店. 非常有效.
  • 可测试性. 可观察对象存储是普通的JavaScript对象,其中隐藏了响应功能. 测试与任何其他JavaScript类的测试相同.
  • 可伸缩性. Observable stores are split logically; there is no difficulty in scaling MobX.
  • 可修改性. MobX允许创建带有修改行为的自定义可观察对象. 另外,还有一个概念叫做反应. 反应模型自动副作用. 这些东西使MobX非常可定制.
  • 可重用性. MobX与框架无关,因此它在可重用性方面非常出色.
  • 生态系统. 有 数百个扩展 适用于MobX.
  • 社区. MobX拥有众多忠实粉丝. 有大约1800个问题(大约1100个回答)带有mobx标签 堆栈溢出.
  • 脉冲. MobX定期更新和维护,与回来的一样,已经达到成熟阶段.

反冲

反冲 是反应团队的最新产物. 它背后的基本思想是missing的一个简单实现 反应特性 比如共享状态和派生数据.

您可能想知道为什么要为企业级项目审查实验性库. 反冲得到了Facebook的支持,并被用于Facebook的一些应用程序中, 并在反应中带来了一种全新的共享状态的方法. 我敢肯定,即使反冲被弃用,另一个工具也会遵循同样的路径,比如 Jotai,将获得关注。.

后坐力建立在两个条件之上: 原子选择器. 原子是一个共享状态块. 组件可以订阅一个原子来获取/设置它的值.

使用反冲描述状态管理的图表, 展示组件如何订阅原子以检索或设置其值.
< / div >

如图所示,当值发生变化时,只会重新呈现订阅的组件. 它使后坐力非常高效.

反冲的另一个优点是 选择器. 选择器是从原子或其他选择器聚合的值. 对于消费者来说, 原子和选择器之间没有区别——它们只需要订阅一些反应部分并使用它.

说明在后坐力中使用选择器的示意图, 它们与原子的关系, 以及不同价值观引起的变化.
< / div >

当一个原子/选择器被改变时,使用它的选择器(例如.e.(被订阅)被重新评估.

后坐力API示例

反冲的代码与其竞争对手有很大的不同. 它基于反应钩子,更关注状态结构,而不是改变状态.

/ /原子/计数器.js
从"recoil"中导入{原子};

const 计数器Atom = 原子({
  关键:“计数器”,
  默认值:0
});

导出默认的计数器Atom;


/ /索引.js
从“反应”导入反应;
从“react-dom”中导入反应DOM;
从“recoil”中导入{反冲Root};
导入App./应用程序”;

反应DOM.呈现(
  <反冲Root>
    
  ,
  文档.getElementById(“根”)
);


/ /应用程序.js
从“反应”导入反应;
从“recoil”导入{use反冲State};
import 计数器Atom./原子/计数器”;

const App = () => {
  const [count, setCount] = use反冲State(计数器Atom);

  回报(
    
{count}
); }; 导出默认App;

质量属性

  • 可用性. 反冲是最容易使用的工具之一,因为它像反应中的useState一样工作.
  • 可维护性. 在反冲中,您所要做的就是在组件中维护选择器和钩子——更多的价值, 更少的样板.
  • 表演. 反冲在反应之外构建一个状态树. 状态树使您能够只获取和收听您需要的内容, 不是整棵树的变化. 它在引擎盖下也得到了很好的优化.
  • 可测试性. 反冲提供 一种机制 用于测试它的原子和选择器.
  • 可伸缩性. 分裂成多个独立部分的状态使其具有特别的可扩展性.
  • 可修改性. 反冲只负责存储值及其聚合. 它没有数据流,因此可以很容易地进行定制.
  • 可重用性. 反冲依赖于反应. 它不能在其他地方重复使用.
  • 生态系统. 目前还没有适合《欧博体育app下载》的生态系统.
  • 社区. 后坐力还很新鲜,不足以形成一个庞大的社区. 有大约200个问题(回答了大约100个)带有recoiljs标签 堆栈溢出.
  • 脉冲. 反冲经常更新,与回来的和MobX相比,在GitHub上有最开放的问题.

哪种工具可以实现反应的最佳状态管理?

当涉及到企业级应用程序时,这些反应全局状态管理库提供了不同的优缺点.

反冲还很年轻,但目前还没有社区和生态系统. 尽管Facebook正在开发它,而且它的API看起来很有前景, 一个庞大的反应应用不能依赖于一个社区支持薄弱的库. 此外,这是实验性的,使其更加不安全. 对于今天的反应企业应用来说,这绝对不是一个好的选择,但值得关注.

MobX和回来的没有这些问题,市场上的大多数大公司都在使用它们. 让他们彼此不同的是他们各自的学习曲线. MobX要求对响应式编程有基本的了解. 如果参与项目的工程师不够熟练, 应用程序可能以代码不一致告终, 性能问题, 增加了开发时间. 如果您的团队意识到反应性,MobX是可以接受的,并且将满足您的需求.

回来的也有一些问题,主要是关于可伸缩性和性能. 然而,与MobX不同的是,这些问题都有经过验证的解决方案.

考虑到每一个优点和缺点, 考虑到我的个人经历, 我推荐回来的作为反应企业级应用程序的最佳选择.

< / div >< / div >< / div >< / div >

关于总博客的进一步阅读:

< / div >

了解基本知识

  • 状态管理在反应中是必要的吗?

    是的,状态管理在反应中是必要的. 事实上, 使用适当的状态管理库是至关重要的,因为反应状态的任何变化都会立即显示给用户

    < / div >< / div >
  • 哪种状态管理在反应中是最好的?

    反应的useState是本地状态管理的最佳选择. 如果您需要全局状态解决方案, 最流行的是回来的, MobX, 以及内置的上下文 API. 您的选择将取决于您的项目的规模、您的需求和您的工程师的专业知识.

    < / div >< / div >
  • 如何在反应中维护全局状态?

    如果保持全局状态干净,维护全局状态很容易. 它应该只包含那些在多个松散连接的组件之间共享的项.

    < / div >< / div >
  • 为什么不使用反应 上下文 API?

    上下文API的功能很小. 它不是为高频更新而构建和优化的,而是为主题更新和认证管理等低频更新而构建和优化的.

    < / div >< / div >
  • 回来的需要很多样板代码吗?

    不,回来的不需要很多样板文件. 随着官方回来的 Toolkit的引入, 在回来的中描述状态管理已经变得简洁.

    < / div >< / div >
  • 我应该怎么做才能精通MobX游戏?

    MobX是用RxJS实现的全局状态管理. 如果你想成为高手,学习RxJS. 它不仅有助于理解单个库, 也适用于整个反应性的概念.

    < / div >< / div >
  • 反冲生产准备好了吗?

    即使在实验阶段,后坐力也表现良好. 这对于大型应用程序来说并不理想, 但对于一个不太依赖政府的小银行来说,这将是有用的.

    < / div >< / div >
< / div >< / div >

标签

< / div >< / div >< / div >< / div >
聘请Toptal这方面的专家.< / div >现在雇佣< / div >< / div >
Teimur Gasanov
< / div >

Teimur Gasanov

验证专家 在工程< / div >< / div >< / div >

比什凯克,Chuy省,吉尔吉斯斯坦

2018年5月1日成为会员

< / div >< / div >< / div >

作者简介

Teimur是反应的导师,也是Toptal核心团队的高级前端工程师.

< / div >< / div >
作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.< / div >

专业知识

反应.js回来的< / div >< / div >

以前在

Klarna< / div >< / div >
雇佣Teimur< / div >< / div >< / div >
< / div >< / div >
< / div >
< / div >
< / div >< / div >< / div >< / div >< / div >
< / div >< / div >
< / div >

世界级的文章,每周发一次.

< / div >

输入您的电子邮件,即表示您同意我们的 隐私政策.

< / div >< / div >< / div >< / div >< div >
< / div >

世界级的文章,每周发一次.

< / div >

输入您的电子邮件,即表示您同意我们的 隐私政策.

< / div >< / div >< / div >< / div >< / div >< / div >< / div >

Toptal开发者

< / div >< / div >

加入总冠军® 社区.

聘请开发人员 or 申请成为发展商< / div >< / div >< / div >