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

Teimur Gasanov

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

专业知识

以前在

Klarna
Share

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

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

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

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

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

内置的React状态管理功能

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

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

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

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

检查现有的React状态管理库

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

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

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

Redux

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

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

动画显示状态和动作的进展,从和到减速器,使用Redux.

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

要在React中使用Redux,您需要通过React - Redux将组件订阅到存储更新.

Redux API示例

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

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

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

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


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

导出默认配置恢复({
  减速机:{
    柜台:counterReducer
  }
});


/ /索引.js
从“React”中导入React
从“react-dom”中导入ReactDOM
从“react-redux”中导入{Provider}
导入应用程序./App'
从'导入存储'./store'

ReactDOM.render(
  
    
  ,
  文档.getElementById(根)
)


// App.js
从“React”导入React;
从“react-redux”中导入{useSelector, useDispatch};
导入{actions}./片/计数器”;

const App = () => {
  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();

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

质量属性

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

MobX

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

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

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

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

MobX API示例

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

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

类CounterStore {
  值= 0;

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

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

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

导出默认的CounterStore;


/ /索引.js
从“React”导入React;
从“react-dom”中导入ReactDOM;
从“mobx-react”中导入{Provider};
导入App./App";
从“./商店/计数器”;

ReactDOM.render(
  
    
  ,
  文档.getElementById(“根”)
);


// App.js
从“React”导入React;
从mobx-react中导入{inject, observer};

const App = inject((stores) => ({ counter: stores.柜台}))(
  observer(({ counter }) => {
    回报(
      
{counter.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标签 堆栈溢出.
  • Pulse. MobX定期更新和维护,与Redux一样,已经达到成熟阶段.

Recoil

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

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

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

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

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

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

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

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

后坐力API示例

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

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

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

导出默认的counterAtom;


/ /索引.js
从“React”导入React;
从“react-dom”中导入ReactDOM;
从“recoil”中导入{RecoilRoot};
导入App./App";

ReactDOM.render(
  
    
  ,
  文档.getElementById(“根”)
);


// App.js
从“React”导入React;
从“recoil”导入{useRecoilState};
import counterAtom./原子/计数器”;

const App = () => {
  const [count, setCount] = useRecoilState(counterAtom);

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

质量属性

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

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

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

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

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

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

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

了解基本知识

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

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

  • 哪种状态管理在React中是最好的?

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

  • 如何在React中维护全局状态?

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

  • 为什么不使用React Context API?

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

  • Redux需要很多样板代码吗?

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

  • 我应该怎么做才能精通MobX游戏?

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

  • Recoil生产准备好了吗?

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

就这一主题咨询作者或专家.
预约电话
Teimur Gasanov的头像
Teimur Gasanov

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

成员自 2018年5月1日

作者简介

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

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

专业知识

以前在

Klarna

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

订阅意味着同意我们的 隐私政策

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

订阅意味着同意我们的 隐私政策

Toptal开发者

加入总冠军® 社区.