# Redux 常见问题:创建 Store

# 目录

  • 可以创建多个 store 吗,应该这么做吗?能在组件中直接引用 store 并使用吗?
  • 在 store enhancer 中可以存在多个 middleware 链吗? 在 middleware 方法中,next 和 dispatch 之间区别是什么?
  • 怎样只订阅 state 的一部分变更?如何将分发的 action 作为订阅的一部分?

# 创建 Store

# 可以创建多个 store 吗,应该这么做吗?能在组件中直接引用 store 并使用吗?

Flux 原始模型中一个应用有多个 “store”,每个都维护了不同维度的数据。这样导致了类似于一个 store “等待” 另一 store 操作的问题。Redux 中将 reducer 分解成多个小而美的 reducer,进而切分数据域,避免了这种情况的发生。

正如上述问题所述,“可能” 在一个页面中创建多个独立的 Redux store,但是预设模式中只会有一个 store。仅维持单个 store 不仅可以使用 Redux DevTools,还能简化数据的持久化及深加工、精简订阅的逻辑处理。

在 Redux 中使用多个 store 的理由可能包括:

  • 对应用进行性能分析时,解决由于过于频繁更新部分 state 引起的性能问题。
  • 在更大的应用中 Redux 只是作为一个组件,这种情况下,你也许更倾向于为每个根组件创建单独的 store。

然而,创建新的 store 不应成为你的第一反应,特别是当你从 Flux 背景迁移而来。首先尝试组合 reducer,只有当它无法解决你的问题时才使用多个 store。

类似的,虽然你 直接导入并获取 store 实例,但这并非 Redux 的推荐方式。当你创建 store 实例并从组件导出,它将变成一个单例。这意味着将很难把 Redux 应用封装成一个应用的子组件,除非这是必要的,或者为了实现服务端渲染需要为每一个请求创建单独的 store 实例。

借助 React Redux,由 connect() 生成的包装类实际上会检索存在的 props.store,但还是推荐将根组件包装在 `` 中,这样传递 store 的任务都交由 React Redux 处理。这种方式,我们不用考虑 store 模块的导入、 Redux 应用的封装,后期支持服务器渲染也将变得更为简便。

# 补充资料

文档

  • API: Store

讨论

  • #1346: Is it bad practice to just have a 'stores' directory?
  • Stack Overflow: Redux multiple stores, why not?
  • Stack Overflow: Accessing Redux state in an action creator
  • Gist: Breaking out of Redux paradigm to isolate apps

# 在 store enhancer 中可以存在多个 middleware 链吗? 在 middleware 方法中,nextdispatch 之间区别是什么?

Redux middleware 就像一个链表。每个 middleware 方法既能调用 next(action) 传递 action 到下一个 middleware,也可以调用 dispatch(action) 重新开始处理,或者什么都不做而仅仅终止 action 的处理进程。

创建 store 时, applyMiddleware 方法的入参定义了 middleware 链。定义多个链将无法正常执行,因为它们的 dispatch 引用显然是不一样的,而且不同的链也无法有效连接到一起。

# 补充资料

文档

  • Advanced: Middleware
  • API: applyMiddleware

讨论

  • #1051: Shortcomings of the current applyMiddleware and composing createStore
  • Understanding Redux Middleware
  • Exploring Redux Middleware

# 怎样只订阅 state 的一部分变更?如何将分发的 action 作为订阅的一部分?

Redux 提供了独立的 store.subscribe 方法用于通知监听器 store 的变更信息。监听器的回调方法并没有把当前的 state 作为入参,它仅仅代表了 有些数据 被更新。订阅者的逻辑中调用 getState() 获取当前的 state 值。

这个 API 是没有依赖及副作用的底层接口,可以用于创建高阶订阅者逻辑。类似 React Redux 的 UI 绑定能为所有连接的组件都创建订阅。也可以用于编写智能的新旧 state 比对方法,从而在某些内容变化时执行额外的逻辑处理。示例 redux-watchredux-subscribe 提供不同的方式用于指定订阅及处理变更。

新的 state 没有传递给监听者,目的是简化 store enhancer 的实现,比如 Redux DevTools。此外,订阅者旨在响应 state 值本身,而非 action。当 action 很重要且需要特殊处理时,使用 middleware。

# 补充资料

文档

  • Basics: Store
  • API: Store

讨论

  • #303: subscribe API with state as an argument
  • #580: Is it possible to get action and state in store.subscribe?
  • #922: Proposal: add subscribe to middleware API
  • #1057: subscribe listener can get action param?
  • #1300: Redux is great but major feature is missing

  • [Redux Addons Catalog: Store Change Subscriptions]
Last Updated: 5/13/2023, 8:55:38 PM