Redux 常见问题解答:商店设置
目录
商店设置
我可以或应该创建多个商店吗?我可以直接导入我的商店,并在组件中自己使用它吗?
原始的 Flux 模式描述了在一个应用程序中拥有多个“存储”,每个存储都保存着不同的领域数据。这可能会带来一些问题,例如需要一个存储“waitFor
”另一个存储来更新。在 Redux 中,由于将单个 reducer 分割成更小的 reducer,已经实现了数据域之间的分离,因此不需要这样做。
与其他几个问题一样,可以在一个页面中创建多个独立的 Redux 存储,但预期模式是只有一个存储。拥有单个存储可以启用 Redux DevTools,使持久化和重新水化数据变得更简单,并简化订阅逻辑。
在 Redux 中使用多个存储的一些有效理由可能包括
- 解决由状态某些部分更新过于频繁导致的性能问题,前提是通过分析应用程序确认了问题。
- 将 Redux 应用程序作为更大应用程序中的组件隔离,在这种情况下,您可能希望为每个根组件实例创建一个存储。
但是,创建新的存储不应该成为您的第一直觉,尤其是在您来自 Flux 背景的情况下。首先尝试 reducer 组合,只有在它不能解决您的问题时才使用多个存储。
同样,虽然您可以通过直接导入来引用您的存储实例,但这并不是 Redux 中推荐的模式。如果您创建了一个存储实例并将其从模块中导出,它将成为一个单例。这意味着如果需要,将更难将 Redux 应用程序作为更大应用程序的组件隔离,或者启用服务器渲染,因为在服务器上,您希望为每个请求创建单独的存储实例。
使用 React Redux,由 connect()
函数生成的包装类实际上会查找 props.store
(如果存在),但最好将您的根组件包装在 <Provider store={store}>
中,并让 React Redux 负责传递存储。这样,组件就不需要担心导入存储模块,并且在以后隔离 Redux 应用程序或启用服务器渲染变得容易得多。
更多信息
文档
讨论
- #1346: 仅仅有一个“stores”目录算是一种不好的实践吗?
- Stack Overflow: Redux 多个存储,为什么不行?
- Stack Overflow: 在 action 创建器中访问 Redux 状态
- Gist: 为了隔离应用程序而打破 Redux 范式
在 store 增强器中拥有多个中间件链是否可以?next
和 dispatch
在中间件函数中的区别是什么?
Redux 中间件就像一个链表。每个中间件函数都可以调用 next(action)
将 action 传递给下一个中间件,调用 dispatch(action)
从列表开头重新开始处理,或者什么也不做以阻止 action 进一步处理。
这个中间件链是由创建存储时使用的 applyMiddleware
函数传递的参数定义的。定义多个链将无法正常工作,因为它们将具有明显不同的 dispatch
引用,并且不同的链实际上将被断开连接。
更多信息
文档
讨论
如何只订阅状态的一部分?我可以将派发的 action 作为订阅的一部分获取吗?
Redux 提供了一个单一的 store.subscribe
方法来通知监听器存储已更新。监听器回调不会接收当前状态作为参数——它只是一个指示某些内容已更改的信号。然后,订阅者逻辑可以调用 getState()
来获取当前状态值。
此 API 旨在作为一种低级原语,没有依赖关系或复杂性,可用于构建更高级别的订阅逻辑。UI 绑定(如 React Redux)可以为每个连接的组件创建订阅。还可以编写函数,这些函数可以智能地比较旧状态与新状态,并在某些部分发生更改时执行其他逻辑。示例包括 redux-watch、redux-subscribe 和 redux-subscriber,它们提供了不同的方法来指定订阅和处理更改。
为了简化实现 Redux DevTools 等存储增强器,不会将新状态传递给监听器。此外,订阅者旨在对状态值本身做出反应,而不是对操作做出反应。如果操作很重要并且需要专门处理,可以使用中间件。
更多信息
文档
讨论
- #303:带有状态作为参数的订阅 API
- #580:是否可以在 store.subscribe 中获取操作和状态?
- #922:提案:将订阅添加到中间件 API
- #1057:订阅监听器可以获取操作参数?
- #1300:Redux 很棒,但缺少主要功能
库