Skip to main content

商店设置

Redux 常见问答:商店设置​

我可以或应该创建多个 store 吗?我能否直接导入我的 store,并自己在组件中使用?​

最初的 Flux 模式描述的是在一个应用中拥有多个“stores”,每个 store 保存不同领域的数据。这可能会引入诸如需要一个 store “waitFor” 另一个 store 更新的问题。在 Redux 中不需要这样做,因为通过将单一 reducer 拆分为多个小的 reducer,已经实现了数据领域的分离。

和其他几个问题类似,在页面中 可以 创建多个独立的 Redux store,但推荐的模式是只有一个 store。拥有单一 store 能够使用 Redux DevTools,使持久化和重新加载数据更简单,并简化订阅逻辑。

使用多个 Redux store 的一些合理理由可能包括:

  • 通过性能分析确认某部分状态更新过于频繁,导致性能问题时使用。
  • 将 Redux 应用隔离为更大应用中的一个组件,在这种情况下,您可能希望为每个根组件实例创建一个 store。

但是,创建新 store 不应成为你的第一选择,特别是如果你来自 Flux 背景。先尝试 reducer 组合,只有在这无法解决问题时才使用多个 store。

类似地,虽然你 可以 直接通过导入方式引用你的 store 实例,但这不是 Redux 推荐的模式。如果你创建 store 实例并从模块中导出它,它将成为单例。这意味着如果需要将 Redux 应用隔离为更大的应用组件,或者启用服务器端渲染时会更困难,因为在服务器上你希望为每个请求创建独立的 store 实例。

使用 React Redux 时,将根组件包裹在 <Provider store={store}> 中,再通过 useSelector 和 useDispatch hooks 从 context 读取 store。这样组件无需导入 store 模块,之后要隔离 Redux 应用或启用服务器渲染也会容易得多。

进一步信息​

文档

讨论

在我的 store enhancer 中使用多个中间件链可以吗?中间件函数中 next 和 dispatch 的区别是什么?​

Redux 中间件就像一个链表。每个中间件函数可以调用 next(action) 将 action 传递给链中的下一个中间件,调用 dispatch(action) 重新从链的开头处理这个 action,或者完全不调用任何函数以阻止该 action 继续被处理。

中间件链通过 configureStore 的 middleware 选项定义(在 Redux 核心层则通过传给 applyMiddleware 的参数定义)。所有中间件都应在同一处加入链中:

const store = configureStore({
reducer: rootReducer,
middleware: getDefaultMiddleware =>
getDefaultMiddleware().concat(loggerMiddleware, analyticsMiddleware)
})

定义多条链无法正常工作,因为它们会有不同的 dispatch 引用,彼此实际上互不相连。

进一步信息​

文档

讨论

如何只订阅部分状态?是否可以在订阅时获取派发的 action?​

Redux 提供了单个的 store.subscribe 方法,用于通知监听者 store 已更新。监听器回调不会接收当前状态作为参数——它只是表明 某些 状态发生了变化。订阅逻辑可以随后调用 getState() 来获取当前状态值。

这个 API 是一个不依赖其他库、结构简单的底层原语,可用于构建更高级的订阅逻辑。React Redux 等 UI 绑定库会用它在每个已订阅组件中重新运行 useSelector。你也可以编写函数,比较新旧状态,并在某些部分发生变化时执行额外逻辑。例如,redux-watch、redux-subscribe 和 redux-subscriber 都提供了不同的订阅定义与变化处理方式。

不把新状态传给 listener,是为了简化 Redux DevTools 等 store enhancer 的实现。此外,订阅者应该响应状态值本身,而不是 action。如果需要响应特定 action 或某部分状态变化来运行逻辑,可以使用 Redux Toolkit 的 createListenerMiddleware:它的 predicate 选项会同时收到 action、旧状态和当前状态。

进一步信息​

文档

讨论