注:我已经阅读了Redux (Baobab也是)的文档,并且我也做了相当一部分的谷歌搜索和测试。
为什么强烈建议Redux应用只有一个商店?
我理解单店和多店的利弊(关于这个问题有很多问答)。
在我看来,这种架构决策应该由应用程序开发人员根据他们的项目需求做出。那么,为什么Redux如此强烈地推荐它,几乎是强制性的(尽管没有什么能阻止我们创建多个商店)?
编辑:转换为单店后的反馈
在与redux一起工作了几个月之后,我可以说,这种单一的商店结构是一种纯粹的乐趣。
以下几点可能有助于其他人理解为什么在许多用例中,单店vs多店是一个没有意义的问题:
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.
几点建议
构建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获取数据的其他部分,很像Dictionary。
当时我还不知道Normalizr,所以我按照同样的思路构建了一些东西。relational-json接受一个模式,并返回一个基于表的接口(有点像数据库)。relational-json的优点是数据结构动态引用数据的其他部分(本质上,您可以在任何方向遍历数据,就像普通的JS对象一样)。它不像Normalizr那样成熟,但几个月来我一直在生产环境中成功地使用它。
当你可能使用多个商店时,也存在一些边缘情况(例如,如果你在每秒多次更新屏幕上同时出现的数千个项目的列表时遇到性能问题)。这是一个例外,在大多数应用中,你只需要一个以上的商店。
为什么我们在文件中强调这一点?因为大多数来自Flux背景的人会认为多个存储是使更新代码模块化的解决方案。然而,Redux对此有不同的解决方案:减速器组合。
将多个减速器进一步分解为一个减速器树,这是在Redux中保持更新模块化的方法。如果你没有意识到这一点,在没有完全理解减速器组成的情况下就去多个存储,你将错过Redux单存储架构的许多好处:
Using reducer composition makes it easy to implement "dependent updates" a la waitFor in 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 waitFor crutch. 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.
为什么我们不能使用多个存储使用redux????
这在Redux中是不必要的,因为数据域之间的分离已经通过将单个减速器拆分为更小的减速器来实现
还原剂。
我是否可以创建多个商店?我可以直接导入我的商店,并自己在组件中使用它吗?
最初的Flux模式描述了在一个应用程序中有多个“商店”,每个商店都拥有不同的领域数据区域。这可能会带来一些问题,比如需要让一个商店“等待”另一个商店更新。
这在Redux中是不必要的,因为数据域之间的分离已经通过将单个减速器拆分为更小的减速器来实现
还原剂。
与其他几个问题一样,可以在一个页面中创建多个不同的Redux存储,但预期的模式是只有一个存储。使用单个存储可以使用Redux DevTools,使数据的持久化和再水化更加简单,并简化了订阅逻辑。
在Redux中使用多个存储的一些有效原因可能包括:
解决由于某些状态的更新过于频繁而导致的性能问题,当通过分析应用程序确认时。
将Redux应用程序隔离为更大应用程序中的组件,在这种情况下,您可能希望为每个根组件实例创建一个存储。
然而,创建新店不应该是你的第一直觉,特别是如果你来自Flux背景。首先尝试减速器组合,如果不能解决你的问题,只使用多个存储。
类似地,虽然可以通过直接导入引用存储实例,但在Redux中不推荐使用这种模式。如果你创建了一个存储实例并从一个模块导出它,它将变成一个单例。这意味着,如果有必要的话,将Redux应用程序隔离为一个更大的应用程序的组件将更加困难,或者启用服务器呈现,因为在服务器上,您希望为每个请求创建单独的存储实例。
redux的官方文件