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

作为一个说明:我已经阅读了Redux的文档(Baobab),我也做了一个公平的分享谷歌和testing。

为什么强烈build议Redux应用程序只有一个商店?

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

海事组织,这个架构决定属于应用程序开发人员根据他们的项目的需求。 那么,为什么强烈build议Redux,几乎到了听起来是强制性的( 虽然没有什么阻止我们做多个商店 )?

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

经过几个月的努力,许多人会认为复杂的SPA,我可以说,单店结构一直是一个纯粹的喜悦合作。

有几点可能会帮助其他人理解为什么单店和多店在许多用例中都是一个毫无疑问的问题:

  • 这是可靠的 :我们使用select器来挖掘应用程序的状态,并获得上下文相关的信息。 我们知道所有需要的数据都在一个商店里。 它避免了所有关于国家问题可能出现的问题。
  • 速度很快 :我们的商店目前有近100个减速器,如果不是更多的话。 即使在这种情况下,只有less数减速器处理任何给定的调度数据,其他的只是返回以前的状态。 一个庞大/复杂的商店( 减速器数量很less)的说法很慢,这实际上是没有实际意义的。 至less我们还没有看到任何性能问题。
  • debugging友好 :虽然这是一个整体使用REDX的最有说服力的说法,但它也适用于单店vs多店。 在构build应用程序时,你肯定会在程序中出现状态错误( 程序员错误 ),这是正常的。 PITA是这些错误需要几个小时才能debugging的时候。 感谢单店( 还有logging器 ),我们从来没有花费几分钟时间处理任何一个州的问题。

几个指针

build立你的redux商店真正的挑战是决定如何构build它。 首先,因为在路上改变结构只是一大痛苦。 其次,因为它在很大程度上决定了你将如何使用,并查询你的应用程序数据的任何过程。 关于如何构build商店有很多build议。 在我们的案例中,我们发现以下是理想的:

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

希望这个反馈将帮助其他人。

编辑2 – 有用的商店工具

对于那些一直想知道如何“轻松”pipe理一家快速变得复杂的单店的人来说 , 有一些工具可以帮助您隔离商店的结构依赖/逻辑。

Normalizr是基于模式规范你的数据。 然后,它提供了一个接口来处理数据,并通过id获取数据的其他部分,就像字典一样。

当时不知道Normalizr,我沿着同样的路线build立了一些东西。 relational-json采用一个模式,并返回一个基于表格的界面( 有点像数据库 )。 relational-json的好处是你的数据结构可以dynamic地引用你数据的其他部分( 本质上,你可以在任何方向遍历你的数据,就像普通的JS对象一样 )。 它不像Normalizr那样成熟,但是现在我已经在生产中成功地使用了它几个月了。

有些情况下可能会使用多个商店(例如,如果您在更新每秒数次同时在屏幕上显示的成千上万个商品列表时遇到性能问题)。 这就是说,这是一个例外,在大多数应用程序,你永远不会需要超过一个单一的商店。

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

将多个还原器分割成一个还原器树,就是如何在Redux中保持更新模块化。 如果你没有认识到这一点,并没有充分理解减速机构成去多家商店,你会错过Redux单店架构的许多好处:

  • 使用reducer组合可以很容易地实现Flux中的“依赖更新”,通过编写一个reducer来手动调用其他reducer,并以特定顺序附加信息。

  • 有了一个店面,坚持,保存和读取状态是非常容易的。 服务器渲染和数据预取是微不足道的,因为只有一个数据存储需要在客户端进行填充和重新水合,JSON可以描述其内容而不用担心商店的ID或名称。

  • 单个商店使得Redux DevTools可以实现时间旅行function。 它还使得像redux-undo或redux-optimist这样的社区扩展变得容易,因为它们在缩减级别上运行。 这种“减速机增强器”不能写入商店。

  • 单个商店保证订阅仅在分发处理完成后才被调用。 也就是说,听众被通知的时候,国家已经完全更新了。 有许多商店,没有这样的保证。 这是Flux需要waitFor拐杖的原因之一。 有了一个店面,这不是你首先看到的问题。

  • 最重要的是,Redux中不需要多个商店(除了性能优势的情况下,无论如何你都应该首先进行configuration)。 我们把它作为文档中的重要一点,所以鼓励您学习Reducer构成和其他Redux模式,而不是像使用Flux一样使用Redux,并且失去它的好处。

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

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

  • pipe理员
  • 分析/数据与仪表板
  • 账单pipe理和采购stream程
  • 企业客户团队/权限pipe理

如果这些东西中的任何一个很小,只要把它们作为主应用程序的一部分。 如果它们变得非常大(如一些企业账户pipe理和分析工具所做的那样),将它们分开。

pipe理非常大的应用程序的最好方法就是把它们当作许多小型应用程序的组合。

如果你的应用程序不到~50K LOC,你可能应该忽略这个build议,而是遵循Dan的build议。

如果您的应用程序超过100万个LOC,那么即使您将它们保存在单声道回购中,您也应该分解出小应用程序。

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

对于所有其他情况,您可能不需要拥有多个商店。 正如丹说的那样,创造体贴的还原剂组合物可以被certificate是更好的解决scheme。

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

不要忘记,商店是在一个JavaScript对象,所以虽然你只有一个商店,它可以很容易地扩展和重用,对我来说,有一个商店使得使用Redux开发工具遍历更容易,而不是混入大的应用程序

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

如果整个应用程序的pipe理得当,一个商店就足以pipe理整个应用程序的状态。