首页 文章

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

提问于
浏览
169

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

Why is it so strongly suggested that a Redux app have only one store?

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

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

EDIT: feedback after converting to single-store

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

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

  • it's reliable :我们使用选择器来挖掘应用程序状态并获取与上下文相关的信息 . 我们知道所有需要的数据都在一个商店中 . 它避免了对状态问题可能出现的所有问题 .

  • it's fast :我们的商店目前有近100个减速机,如果不是更多的话 . 即使按此计算,只有少数减速器处理任何给定调度的数据,其他减少器只返回先前的状态 . 一个巨大/复杂的商店(减速器的nbr)缓慢的论点几乎没有实际意义 . 至少我们没有看到任何性能问题 .

  • debugging friendly :虽然这是使用redux作为一个整体的最有说服力的论据,但它也适用于单店和多店 . 在构建应用程序时,您必然会在进程中出现状态错误(程序员错误),这是正常的 . PITA是那些错误需要几个小时才能调试的时候 . 感谢单店(和redux-logger),我们在任何给定的状态问题上都没有花费超过几分钟的时间 .

a few pointers

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

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

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

编辑2 - 有用的商店工具

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

Normalizr可根据模式规范化您的数据 . 然后它提供了一个界面来处理数据并通过 id 获取数据的其他部分,就像字典一样 .

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

5 回答

  • 14

    在Redux中拥有一家商店是我们在许多情况下所需要的,我使用Redux和Flux并相信Redux能够更好地完成工作!

    不要忘记商店是一个JavaScript对象,所以虽然你只有一个商店,它可以很容易地扩展和重用,对我来说,拥有一个商店使得使用Redux开发工具更容易遍历并且不会混淆大应用......

    另外一个商店的概念是为我们模仿数据库,一个事实来源,你可以改变它,你可以在浏览器内存中访问它...

    如果整个应用程序管理良好,一个商店就足以管理整个应用程序状态......

  • 3

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

    为什么我们在文档中强调这一点?因为大多数来自Flux背景的人都会 assume multiple stores is the solution to making update code modular. However Redux has a different solution for this: reducer composition.

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

    • 使用reducer组合可以轻松地在Flux中实现"dependent updates" a la waitFor ,方法是手动调用其他Reducer以及其他信息并按特定顺序调用 .

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

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

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

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

  • 3

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

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

    • 管理员

    • 分析/数据访问仪表板

    • 结算管理和采购流程

    • 企业客户团队/权限管理

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

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

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

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

  • 1

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

    你生活在自己的世界里 . 我正在与使用redux的人会面,因为它每天都很受欢迎 . 你甚至无法想象有多少项目在没有任何决策的情况下开始减少 . 我讨厌redux方法,但不得不使用它,因为其他开发人员什么都不知道 . 这只是facebook膨胀的史诗泡沫 .

    • It's not reliable 因为商店的某些部分未被隔离 .

    • It's inefficient 因为你正在克隆和遍历哈希特里 . 当突变以算术方式增长时 - 复杂性在几何上增长 . 您无法通过重构任何减速器,选择器等来修复它 . 您必须拆分您的trie .

    • When it become slow 没有人想将它拆分为具有单独商店的单独应用程序 . 没有人愿意花钱进行重构 . 人们通常是 converting some smart components into dump 就是这样 . 你知道还有等待redux开发人员的未来吗?他们将维持这些地狱 .

    • It's not debugging friendly . 在商店的几乎隔离的部分之间调试连接很困难 . 即使分析这些连接的数量也很困难 .

    让我们假设你有几个redux商店 . 您将打破单向数据流 . 您将立即意识到您的商店之间有多少联系 . 你可能会受到这些联系的困扰,与圆形代表队战斗等 .

    具有单向流动的单一不可变存储不是每种疾病的灵丹妙药 . 如果您不想维护项目架构,那么无论如何都会受到影响 .

  • 177

    在以下用例中,多个存储可能会有所帮助1.如果您有大型组件在数据结构,行为,应用程序上下文方面彼此独立 . 隔离这些组件可以更轻松地管理数据和应用程序流 . 它还有助于组件的独立开发和维护 . 2.性能问题:不是典型的用例,但如果您的某些组件非常频繁地更新并且对其他组件没有任何影响,那么您可能会去不同的商店 .

    对于所有其他情况,您可能不需要拥有多个商店 . 正如丹所说,创造周到的减速剂成分可以证明是更好的解决方案 .

相关问题