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

Seb*_*iel 196 javascript redux

作为一个注释:我已经阅读了Redux的文档(Baobab也是如此),并且我已经做了很多Google搜索和测试.

为什么Redux应用程序只有一个商店?

我理解单店设置与多店设置的优缺点(在这个主题上有很多关于SO的问答).

IMO,这个架构决策属于应用程序开发人员根据他们的项目需求.那么为什么Redux如此强烈建议,几乎到了强制性的声音(虽然没有什么能阻止我们制作多个商店)?

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

在使用redux处理许多人认为复杂的SPA之后几个月,我可以说单一商店结构一直是一种纯粹的乐趣.

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

  • 它是可靠的:我们使用选择器来挖掘应用程序状态并获取与上下文相关的信息.我们知道所有需要的数据都在一个商店中.它避免了对状态问题可能存在的所有质疑.
  • 速度很快:我们的商店目前有近100个减速机,如果不是更多的话.即使在那个数量上,只有少数减速器处理任何给定调度的数据,其他减少器只返回先前的状态.一个巨大/复杂的商店(减速器的数量)缓慢的论点几乎没有实际意义.至少我们没有看到任何性能问题.
  • 调试友好:虽然这是使用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
}
Run Code Online (Sandbox Code Playgroud)

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

编辑2 - 有用的商店工具

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

Normalizr其标准化基础上的模式数据.然后它提供了一个界面来处理数据并获取数据的其他部分id,就像字典一样.

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

Dan*_*mov 212

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

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

将多个Reducer进一步拆分为reducer树,就是如何在Redux中保持模块更新.如果您没有认识到这一点并且在没有完全理解减速器组成的情况下去多个商店,那么您将会错过Redux单店架构的许多好处:

  • 使用reducer组合可以轻松地waitFor在Flux中实现"依赖更新" ,通过手动编写减速器以及其他信息并按特定顺序调用其他减速器.

  • 只需一个商店,就可以很容易地保持,保湿和阅读状态.服务器呈现和数据预取是微不足道的,因为只需要在客户端上填充和重新水化一个数据存储,JSON可以描述其内容而不必担心商店的ID或名称.

  • 单个商店使Redux DevTools的时间旅行功能成为可能.它还使像redux-undo或redux-optimist这样的社区扩展变得容易,因为它们在reducer级别上运行.这种"减速剂增强剂"不能用于商店.

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

  • 最重要的是,Redux中不需要多个商店(除了您应该首先分析的性能边缘情况).我们将其作为文档中的重点,因此我们鼓励您学习减速器组合和其他Redux模式,而不是像使用Flux一样使用Redux,并且失去它的好处.

  • 我承认我不理解减速剂成分的全部优势/必要性.感谢您的回答,我做了一些更多的阅读和一个例子(TodoMVC,再次).在这么小的例子中,很难理解还原剂组合物提供的实际改进.然而,经过一番思考,大规模的增益(现在)显而易见.再次感谢,很好的答案! (11认同)
  • @ natlee75"在Redux中使用多个存储的一些正当理由可能包括:[...]将Redux应用程序隔离为更大应用程序中的组件,在这种情况下,您可能希望为每个根组件实例创建一个存储." 来自http://redux.js.org/docs/FAQ.html#store-setup-multiple-stores (6认同)
  • @DanAbramov好奇你的主要"应用程序"运行自己的Redux商店并通过npm导入运行其自己独立的Redux商店的独立"应用程序"的情况.例如,如果贵公司的其他团队中的某个团队拥有某种带有您想要引入的UI的消息服务,而不会使用该数据污染您的商店. (5认同)
  • @Sebastien我认为"购物车"的例子对我来说更好. (4认同)
  • 我正在慢慢地将redux实现到传统(非SPA)应用程序中.我正在为每个"整体"使用multilpe存储我转换为react/redux实现,直到可以修改整个应用程序以使用相同的存储. (3认同)

Eri*_*ott 20

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

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

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

如果这些东西中的任何一个很小,只需将它们作为主应用程序的一部分.如果它们变得非常大(如某些企业帐户管理和分析工具那样),请将它们分开.

管理非常大的应用程序的最佳方法是将它们视为许多较小应用程序的组合.

如果您的应用程序低于~50k LOC,您可能应该忽略此建议并遵循Dan的建议.

如果您的应用程序超过1百万LOC,您可能应该拆分迷你应用程序,即使您将它们保存在单声道回购中.


Riz*_*izo 8

为什么我们不能使用 redux 来使用多个存储???

\n\n
\n

这在 Redux 中是不必要的,因为数据域之间的分离已经通过将单个化简器拆分为更小的化简器来实现。

\n
\n\n
\n\n

我可以或者应该创建多个商店吗?我可以直接导入我的商店并自己在组件中使用它吗?

\n\n

最初的 Flux 模式描述了应用程序中有多个 \xe2\x80\x9cstores\xe2\x80\x9d,每个存储区保存不同的域数据区域。这可能会带来问题,例如需要一个存储 \xe2\x80\x9cwaitFor\xe2\x80\x9d 另一个存储进行更新。

\n\n
\n

这在 Redux 中是不必要的,因为数据域之间的分离已经通过将单个化简器拆分为更小的化简器来实现。

\n
\n\n

与其他几个问题一样,可以在一个页面中创建多个不同的 Redux 存储,但预期的模式是只有一个存储。拥有单个存储可以使用 Redux DevTools,使数据的持久化和补充变得更简单,并简化订阅逻辑。

\n\n

在 Redux 中使用多个存储的一些正当理由可能包括:

\n\n

通过分析应用程序确认后,解决因状态某些部分更新过于频繁而导致的性能问题。\n将 Redux 应用程序隔离为更大应用程序中的组件,在这种情况下,您可能希望为每个根组件实例创建一个存储.\n但是,创建新商店不应该是您的第一本能,特别是如果您来自 Flux 背景。首先尝试减速器组合,如果不能解决您的问题,则仅使用多个存储。

\n\n

同样,虽然您可以通过直接导入来引用您的商店实例,但这不是 Redux 中推荐的模式。如果您创建一个商店实例并将其从模块中导出,它将成为一个单例。这意味着将 Redux 应用程序隔离为大型应用程序的组件(如果有必要的话)或启用服务器渲染将变得更加困难,因为您希望在服务器上为每个请求创建单独的存储实例。

\n\n

redux 的官方文档

\n


puc*_*chu 5

根据应用程序开发人员的项目需求,此架构决定属于他们

您生活在自己的世界中。我每天都在与使用redux的人见面,因为它很流行。您甚至无法想象没有任何决定就开始重新启动多少项目。我讨厌redux方法,但不得不使用它,因为其他开发人员一无所知。这只是Facebook膨胀的史诗般的泡沫。

  • 这是不可靠的,因为商店的各个部分不是孤立的。
  • 这是低效率的,因为您正在克隆和遍历哈希树。当突变以算术方式增长时,复杂性就会以几何方式增长。您无法通过重构任何化简器,选择器等来修复它。您必须拆分Trie。
  • 当它变慢时,没有人希望将其拆分为带有单独存储的单独应用程序。没有人愿意花钱在重构上。人们通常将一些智能组件转换为转储,仅此而已。您知道Redux开发人员正在等待什么未来吗?他们将维持这些地狱。
  • 它不是调试友好的。很难调试商店中几乎隔离的部分之间的连接。甚至很难分析这些连接的数量。

假设您有几个redux存储。您将中断单向数据流。您将立即意识到商店之间有多少联系。您可能会遭受这些连接的困扰,与圆形部门战斗等。

具有单向流动的单一不可变存储并不是每种疾病的灵丹妙药。如果您不想维护项目体系结构,那么无论如何您都会遭受痛苦。