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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33619775/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 15:17:04  来源:igfitidea点击:

Redux - multiple stores, why not?

javascriptredux

提问by Sebastien Daniel

As a note: I've read the docs for Redux (Baobab, too), and I've done a fair share of Googling & testing.

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

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

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

I understand the pros/cons of a single-store setup vs a multiple store setup (There are many Q&A on SO on this subject).

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

IMO, this architectural decision belongs to the app developers based on their projects' needs. So why is it so strongly suggested for Redux, almost to the point of sounding mandatory (though nothing is stopping us from making multiple stores)?

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

EDIT: feedback after converting to single-store

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

After a few months working with redux on what many would consider a complex SPA, I can say that the single store structure has been a pure delight to work with.

在与 redux 合作开发了许多人认为复杂的 SPA 几个月后,我可以说单一存储结构的使用是一种纯粹的乐趣。

A few points that might help others understand why single store vs many store is a moot question in many, many use-cases:

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

  • it's reliable: we use selectors to dig through the app state and obtain context-relevant information. We know that all the needed data is in a single store. It avoids all questioning as to where state issues could be.
  • it's fast: our store currently has close to 100 reducers, if not more. Even at that count, only a handful of reducers process data on any given dispatch, the others just return the previous state. The argument that a huge/complex store (nbr of reducers) is slow is pretty much moot. At least we've not seen any performance issues coming from there.
  • debugging friendly: while this is a most convincing argument to use redux as a whole, it also goes for single store vs multiple store. When building an app you're bound to have state errors in the process (programmer mistakes), it's normal. The PITA is when those errors take hours to debug. Thanks to the single store (and redux-logger) we've never spent more than a few minutes on any given state issue.
  • 它是可靠的:我们使用选择器来挖掘应用程序状态并获取与上下文相关的信息。我们知道所有需要的数据都在一个存储中。它避免了关于国家问题可能在哪里的所有质疑。
  • 速度很快:我们的商店目前有近 100 台减速机,甚至更多。即使在这个数量上,也只有少数 reducer 处理任何给定调度的数据,其他人只返回之前的状态。一个巨大/复杂的存储(减速器的 nbr)很慢的论点几乎没有实际意义。至少我们没有看到任何性能问题来自那里。
  • 调试友好:虽然这是整体使用 redux 的最有说服力的论据,但它也适用于单店与多店。在构建应用程序时,您肯定会在过程中出现状态错误(程序员错误),这是正常的。PITA 是这些错误需要数小时才能调试的时候。多亏了单一存储(和 redux-logger),我们从来没有在任何给定的状态问题上花费超过几分钟的时间。

a few pointers

一些提示

The true challenge in building your redux store is when deciding how to structureit. Firstly, because changing structure down the road is just a major pain. Secondly, because it largely determines how you'll be using, and querying your app data for any process. There are many suggestions on how to structure a store. In our case we found the following to be ideal:

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

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

Hopefully this feedback will help others.

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

EDIT 2 - helpful store tools

编辑 2 - 有用的商店工具

For those of you who have been wondering how to "easily" manage a single store, which can quickly get complex. There are a tools that help isolate the structural dependencies/logic of your store.

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

There is Normalizrwhich normalizes your data based on a schema. It then provides an interface to work with your data and fetch other parts of your data by id, much like a Dictionary.

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

Not knowing Normalizr at the time, I built something along the same lines. relational-jsontakes a schema, and returns a Table-based interface (a little like a database). The advantage of relational-json is that your data structure dynamically references other parts of your data (essentially, you can traverse your data in any direction, just like normal JS objects). It's not as mature as Normalizr, but I've been using it successfully in production for a few months now.

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

回答by Dan Abramov

There are edge cases when you might use multiple stores (e.g. if you have performance problems with updating lists of thousands of items that are on screen at the same time many times per second). That said it's an exception and in most apps you never need more than a single store.

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

Why do we stress this in the docs? Because most people coming from Flux background will assume multiple stores is the solution to making update code modular. However Redux has a different solution for this: reducer composition.

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

Having multiple reducers that are further split into a reducer tree is how you keep updates modular in Redux. If you don't recognize this and go for multiple stores without fully understanding reducer composition first, you will miss many benefits of Redux single store architecture:

将多个 reducer 进一步拆分为一个 reducer 树是您在 Redux 中保持更新模块化的方式。如果你没有认识到这一点,在没有完全理解 reducer 组合的情况下去多个 store,你将错过 Redux 单存储架构的许多好处:

  • Using reducer composition makes it easy to implement "dependent updates" a la waitForin Flux by writing a reducer manually calling other reducers with additional information and in a specific order.

  • With a single store, it's very easy to persist, hydrate, and read the state. Server rendering and data prefetching is trivial because there is just one data storage that needs to be filled and rehydrated on the client, and JSON can describe its contents without worrying about store's ID or name.

  • A single store makes Redux DevTools time travel features possible. It also makes community extensions like redux-undo or redux-optimist easy because they operate on the reducer level. Such "reducer enhancers" can't be written for stores.

  • A single store guarantees that the subscriptions are called only after the dispatch has been processed. That is, by the time listeners are notified, the state has been fully updated. With many stores, there are no such guarantees. This is one of the reasons Flux needs the waitForcrutch. With a single store, this is not a problem you see in the first place.

  • Above all, multiple stores are unnecessary in Redux (except for performance edge cases which you are supposed to profile first anyway). We make it an important point in the docs so you are encouraged to learn reducer composition and other Redux patterns instead of using Redux as if it was Flux, and losing its benefits.

  • 使用 reducer 组合可以很容易地waitFor在 Flux 中实现“依赖更新” ,方法是编写一个 reducer,以特定的顺序手动调用其他带有附加信息的 reducer。

  • 使用单个存储,很容易持久化、保湿和读取状态。服务器渲染和数据预取是微不足道的,因为客户端上只有一个数据存储需要填充和再水化,而 JSON 可以描述其内容,而无需担心存储的 ID 或名称。

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

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

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

回答by Eric Elliott

In some very large enterprise apps with hundreds or thousands of reducers, it's often useful to think of different areas of the app as entirely separate apps. In those cases (where it really is multiple apps that share a domain name), I use multiple stores.

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

For example, I tend to treat the following common functionality areas as separate apps:

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

  • Admin
  • Analytics / data vis dashboards
  • Billing management & purchase flows
  • Enterprise account team/permission management
  • 行政
  • 分析/数据与仪表板
  • 计费管理和购买流程
  • 企业客户团队/权限管理

If any of those things are small, just keep them as part of the main app. If they grow very large (as some enterprise account management & analytics tools do), split them out.

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

The best way to manage very large apps is to treat them like a composition of many smaller apps.

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

If your app is less than say ~50k LOC, you should probably ignore this advice and follow Dan's advice, instead.

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

If your app is more than 1 Million LOC, you should probably be splitting out mini-apps, even if you maintain them in a mono repo.

如果您的应用程序超过 100 万个 LOC,您可能应该拆分小应用程序,即使您将它们维护在单一存储库中。

回答by puchu

This architectural decision belongs to the app developers based on their projects' needs

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

You are living in your own world. I am meeting with people that uses redux, because it is popular, everyday. You couldn't even imagine how much projects was started reduxing without any decisioning. I hate redux approaches but had to use it, because other developers knows nothing else. It's just an epic bubble inflated by facebook.

你活在你自己的世界里。我正在与使用 redux 的人会面,因为它每天都很流行。你甚至无法想象有多少项目在没有任何决定的情况下就开始了 redux。我讨厌 redux 方法,但不得不使用它,因为其他开发人员一无所知。这只是脸书膨胀的史诗般的泡沫。

  • It's not reliablebecause parts of store are not isolated.
  • It's inefficientbecause you are cloning and traversing hash trie. When mutations grows arithmetically - complexity grows geometrically. You couldn't fix it by refactoring any reducers, selectors, etc. You have to split your trie.
  • When it become slownobody wants to split it into separate applications with separate stores. Nobody wants to spend money on refactoring. People are usually converting some smart components into dumpand that's it. Do you know what future is waiting for redux developers? They will maintain these hells.
  • It's not debugging friendly. It's hard to debug connections between virtually isolated parts of store. It is very hard even to analyze the amount of these connections.
  • 它不可靠,因为商店的部分不是孤立的。
  • 这是低效的,因为您正在克隆和遍历哈希树。当突变以算术方式增长时 - 复杂性以几何方式增长。您无法通过重构任何减速器、选择器等来修复它。您必须拆分您的尝试。
  • 当它变慢时,没有人愿意将其拆分为具有单独存储的单独应用程序。没有人愿意花钱重构。人们通常将一些智能组件转换为转储,仅此而已。你知道等待 redux 开发者的是什么未来吗?他们将维护这些地狱。
  • 这不是调试友好的。很难调试商店几乎孤立的部分之间的连接。甚至分析这些连接的数量也非常困难。

Let's imagine that you have several redux stores. You will break unidirectional data flow. You will immediately realize how much connections between stores you have. You can suffer from these connections, fighting with circular deps, etc.

假设你有几个 redux store。您将打破单向数据流。您会立即意识到您的商店之间有多少联系。您可能会受到这些连接的困扰,与循环 deps 斗争等。

Single immutable store with unidirectional flow is not an elixir for every disease. If you don't want to maintain project architecture you will suffer anyway.

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

回答by newtonflash

Multiple stores can be helpful in the following use cases 1. If you have large components that are independent of each other in terms of data structure, behavior, application context. Isolating these components make it easier to manage your data and application flow. It also helps independent development and maintenance of your components. 2. Performance problems: not a typical use case, but if some of your components are updating very frequently and does not have any impact on other components, probably you can go for different stores.

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

For all other cases, you may not need to have multiple stores. As Dan says, creating thoughtful reducer compositions can prove to be better solution.

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

回答by Rizo

why we can't use multiple store using redux????

为什么我们不能使用 redux 使用多个商店????

This is not necessary in Redux because the separation between data domains is already achieved by splitting a single reducer into smaller reducers.

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



Can or should I create multiple stores? Can I import my store directly, and use it in components myself?

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

The original Flux pattern describes having multiple “stores” in an app, each one holding a different area of domain data. This can introduce issues such as needing to have one store “waitFor” another store to update.

最初的 Flux 模式描述了在一个应用程序中有多个“商店”,每个商店都保存着域数据的不同区域。这可能会引入一些问题,例如需要让一个商店“等待”另一家商店进行更新。

This is not necessary in Redux because the separation between data domains is already achieved by splitting a single reducer into smaller reducers.

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

As with several other questions, it is possible to create multiple distinct Redux stores in a page, but the intended pattern is to have only a single store. Having a single store enables using the Redux DevTools, makes persisting and rehydrating data simpler, and simplifies the subscription logic.

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

Some valid reasons for using multiple stores in Redux might include:

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

Solving a performance issue caused by too frequent updates of some part of the state, when confirmed by profiling the app. Isolating a Redux app as a component in a bigger application, in which case you might want to create a store per root component instance. However, creating new stores shouldn't be your first instinct, especially if you come from a Flux background. Try reducer composition first, and only use multiple stores if it doesn't solve your problem.

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

Similarly, while you can reference your store instance by importing it directly, this is not a recommended pattern in Redux. If you create a store instance and export it from a module, it will become a singleton. This means it will be harder to isolate a Redux app as a component of a larger app, if this is ever necessary, or to enable server rendering, because on the server you want to create separate store instances for every request.

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

official doc by redux

redux 的官方文档

回答by Alireza

Having one store in Redux is really what we need in many cases, I both used Redux and Flux and believe Redux does the job better!

在许多情况下,在 Redux 中拥有一家商店确实是我们所需要的,我都使用了 Redux 和 Flux,并且相信 Redux 做得更好!

Don't forget the store is in a JavaScript Object, so while you have only one store, it can be easily extended and reused, to me, having one store make it much easier to traversing using Redux dev tools and not be mixed up in big applications...

不要忘记 store 是在一个 JavaScript 对象中,所以当你只有一个 store 时,它​​可以很容易地扩展和重用,对我来说,拥有一个 store 可以更容易地使用 Redux 开发工具进行遍历,并且不会被混淆大应用...

Also the concept of one store is mimicking the database for us, one source of truth which you can change it and you can access it in the browser memory...

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

If the whole application be well-managed, one store can be enough to manage the whole application status...

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