Redux - 多个商店,为什么不呢?

2022-08-30 00:24:38

请注意:我已经阅读了Redux(Baobab)的文档,并且我已经做了相当多的谷歌搜索和测试。

为什么如此强烈地建议Redux应用程序只有一个商店?

我了解单店设置与多店设置的利弊(关于这个主题有很多关于SO的问答)。

IMO,此架构决定属于应用程序开发人员,具体取决于其项目的需求。那么,为什么Redux如此强烈地建议使用它,几乎到了听起来强制性的地步(尽管没有什么能阻止我们制作多个商店)?

编辑:转换为单店后的反馈

在与redux合作几个月后,许多人认为这是一个复杂的SPA,我可以说,单一商店结构是一种纯粹的乐趣。

有几点可以帮助其他人理解为什么单个商店与许多商店在许多用例中是一个没有实际意义的问题:

  • 它是可靠的:我们使用选择器来挖掘应用程序状态并获取与上下文相关的信息。我们知道,所有需要的数据都在一个存储中。它避免了所有关于国家问题可能在哪里的问题。
  • 它很快:我们的商店目前有近100个减速器,如果不是更多的话。即使在这个计数下,也只有少数化简器处理任何给定调度的数据,其他化简器只返回以前的状态。一个巨大的/复杂的存储(nbr的化简器)很慢的论点几乎是没有意义的。至少我们还没有看到任何来自那里的性能问题。
  • 调试友好:虽然这是使用整个redux的最有说服力的论点,但它也适用于单个商店与多个商店。在构建应用程序时,您必然会在过程中出现状态错误(程序员错误),这是正常的。PITA 是当这些错误需要数小时才能调试时。多亏了单一存储(和 redux-logger),我们从未在任何给定的状态问题上花费超过几分钟的时间。

一些提示

构建 redux 商店的真正挑战是在决定如何构建它时。首先,因为改变结构只是一个主要的痛苦。其次,因为它在很大程度上决定了您将如何使用,以及查询任何进程的应用数据。关于如何构建商店有很多建议。在我们的例子中,我们发现以下内容是理想的:

{
  apis: {     // data from various services
    api1: {},
    api2: {},
    ...
  }, 
  components: {} // UI state data for each widget, component, you name it 
  session: {} // session-specific information
}

希望这些反馈能够帮助其他人。

编辑2 - 有用的商店工具

对于那些一直想知道如何“轻松”管理单个商店的人来说,这可能会很快变得复杂。有一些工具可以帮助隔离商店的结构依赖关系/逻辑。

Normalizr可以根据架构规范化您的数据。然后,它提供了一个接口来处理您的数据,并通过 获取数据的其他部分,就像字典一样。id

当时我不了解Normalizr,所以我按照同样的路线构建了一些东西。relational-json 采用一个模式,并返回一个基于表的接口(有点像数据库)。relational-json的优点是你的数据结构动态地引用数据的其他部分(本质上,你可以在任何方向上遍历数据,就像普通的JS对象一样)。它不像Normalizr那样成熟,但我已经在生产中成功地使用了几个月了。


答案 1

在一些边缘情况下,您可能会使用多个商店(例如,如果您在每秒多次更新屏幕上同时出现的数千个项目的列表时遇到性能问题)。也就是说,这是一个例外,在大多数应用程序中,您永远不需要超过一个商店。

为什么我们在文档中强调这一点?因为大多数来自Flux背景的人会认为多个商店是使更新代码模块化的解决方案。然而,Redux对此有不同的解决方案:减速器组成。

将多个进一步拆分为一个化简器树的化简器,就是如何在 Redux 中保持更新的模块化方式。如果您没有意识到这一点,并且在没有首先完全了解化简器组成的情况下选择了多个商店,那么您将错过Redux单商店架构的许多好处:

  • 使用化简器组合,通过编写化简器,手动调用具有附加信息和特定顺序的其他化简器,可以轻松实现“依赖更新”。waitFor

  • 使用单个存储,很容易持久化,水合和读取状态。服务器呈现和数据预取是微不足道的,因为客户端上只需要填充和重新冻结一个数据存储,JSON可以描述其内容,而不必担心存储的ID或名称。

  • 单个存储使 Redux DevTools 时间旅行功能成为可能。它还使像redux-undo或redux-optimist这样的社区扩展变得容易,因为它们在 reducer 级别运行。这样的“减速器增强剂”不能为商店编写。

  • 单个存储保证仅在处理调度后才调用订阅。也就是说,在通知侦听器时,状态已完全更新。对于许多商店,没有这样的保证。这是Flux需要拐杖的原因之一。对于单个商店,这首先不是您看到的问题。waitFor

  • 最重要的是,在 Redux 中不需要多个存储(除了性能边缘情况,无论如何,您都应该首先分析)。我们在文档中将其作为重要观点,因此鼓励您学习化简器组合和其他Redux模式,而不是像使用Flux一样使用Redux,并失去其优势。


答案 2

在一些具有数百或数千个化简器的非常大的企业应用中,将应用的不同区域视为完全独立的应用通常很有用。在这些情况下(实际上是多个应用程序共享一个域名),我使用多个商店。

例如,我倾向于将以下常见功能区域视为单独的应用程序:

  • 管理
  • 分析/数据可视化仪表板
  • 计费管理和购买流程
  • 企业帐户团队/权限管理

如果其中任何一个很小,只需将它们保留为主应用程序的一部分即可。如果它们变得非常大(就像一些企业帐户管理和分析工具所做的那样),请将它们拆分出来。

管理超大型应用的最佳方法是将它们视为许多较小应用的组成。

如果你的应用小于 ~50k LOC,则可能应忽略此建议并遵循 Dan 的建议。

如果你的应用超过 100 万个 LOC,则可能应该拆分出迷你应用,即使你在单一存储库中维护它们也是如此。