Skip to main content

Redux 常见问题解答:存储设置

¥Redux FAQ: Store Setup

目录

¥Table of Contents

存储设置

¥Store Setup

我可以或者应该创建多个存储吗?我可以直接导入我的存储并自己在组件中使用它吗?

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

最初的 Flux 模式描述了在应用中拥有多个“存储”,每个“存储”保存不同区域的域数据。这可能会带来一些问题,例如需要一个存储“waitFor”另一个存储进行更新。这在 Redux 中是不必要的,因为数据域之间的分离已经通过将单个 reducer 拆分为更小的 reducer 来实现。

¥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. This is not necessary in Redux because the separation between data domains is already achieved by splitting a single reducer into smaller reducers.

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

¥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 中使用多个存储的一些正当理由可能包括:

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

  • 通过分析应用确认后,解决由于状态某些部分更新过于频繁而导致的性能问题。

    ¥Solving a performance issue caused by too frequent updates of some part of the state, when confirmed by profiling the app.

  • 将 Redux 应用隔离为更大应用中的组件,在这种情况下,你可能希望为每个根组件实例创建一个存储。

    ¥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.

然而,创建新存储不应该是你的第一反应,特别是如果你来自 Flux 背景。首先尝试 reducer 组合,如果不能解决你的问题,则仅使用多个存储。

¥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 中推荐的模式。如果你创建一个存储实例并将其从模块中导出,它将成为一个单例。这意味着将 Redux 应用隔离为大型应用的组件(如果有必要的话)或启用服务器渲染将变得更加困难,因为你希望在服务器上为每个请求创建单独的存储实例。

¥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.

对于 反应还原,由 connect() 函数生成的封装类实际上会查找 props.store(如果存在),但最好将根组件封装在 <Provider store={store}> 中,并让 React Redux 负责传递存储。这样组件就不需要担心导入存储模块,并且以后隔离 Redux 应用或启用服务器渲染会更容易。

¥With React Redux, the wrapper classes generated by the connect() function do actually look for props.store if it exists, but it's best if you wrap your root component in <Provider store={store}> and let React Redux worry about passing the store down. This way components don't need to worry about importing a store module, and isolating a Redux app or enabling server rendering is much easier to do later.

更多信息

¥Further information

文档

¥Documentation

讨论

¥Discussions

我的存储增强器中可以有多个中间件链吗?中间件函数中 nextdispatch 有什么区别?

¥Is it OK to have more than one middleware chain in my store enhancer? What is the difference between next and dispatch in a middleware function?

Redux 中间件就像一个链表。每个中间件函数可以调用 next(action) 将操作传递到队列中的下一个中间件,调用 dispatch(action) 在列表开头重新启动处理,或者不执行任何操作以停止进一步处理操作。

¥Redux middleware act like a linked list. Each middleware function can either call next(action) to pass an action along to the next middleware in line, call dispatch(action) to restart the processing at the beginning of the list, or do nothing at all to stop the action from being processed further.

该中间件链由传递给创建存储时使用的 applyMiddleware 函数的参数定义。定义多个链将无法正常工作,因为它们将具有明显不同的 dispatch 引用,并且不同的链将有效地断开连接。

¥This chain of middleware is defined by the arguments passed to the applyMiddleware function used when creating a store. Defining multiple chains will not work correctly, as they would have distinctly different dispatch references and the different chains would effectively be disconnected.

更多信息

¥Further information

文档

¥Documentation

讨论

¥Discussions

我如何只订阅状态的一部分?我可以将已调度的操作作为订阅的一部分吗?

¥How do I subscribe to only a portion of the state? Can I get the dispatched action as part of the subscription?

Redux 提供了一个 store.subscribe 方法来通知监听器存储已更新。监听器回调不接收当前状态作为参数 - 它只是表明某些事情已经发生了变化。然后订阅者逻辑可以调用 getState() 来获取当前状态值。

¥Redux provides a single store.subscribe method for notifying listeners that the store has updated. Listener callbacks do not receive the current state as an argument—it is simply an indication that something has changed. The subscriber logic can then call getState() to get the current state value.

该 API 旨在作为没有依赖或复杂性的底层原语,可用于构建更高级别的订阅逻辑。React Redux 等 UI 绑定可以为每个连接的组件创建订阅。还可以编写可以智能比较旧状态与新状态的函数,并在某些部分发生更改时执行附加逻辑。示例包括 redux-watchredux-subscriberedux-subscriber,它们提供了不同的方法来指定订阅和处理更改。

¥This API is intended as a low-level primitive with no dependencies or complications, and can be used to build higher-level subscription logic. UI bindings such as React Redux can create a subscription for each connected component. It is also possible to write functions that can intelligently compare the old state vs the new state, and execute additional logic if certain pieces have changed. Examples include redux-watch, redux-subscribe and redux-subscriber which offer different approaches to specifying subscriptions and handling changes.

新状态不会传递给监听器,以简化存储增强器(例如 Redux DevTools)的实现。此外,订阅者的目的是对状态值本身做出反应,而不是对操作做出反应。如果操作很重要并且需要专门处理,则可以使用中间件。

¥The new state is not passed to the listeners in order to simplify implementing store enhancers such as the Redux DevTools. In addition, subscribers are intended to react to the state value itself, not the action. Middleware can be used if the action is important and needs to be handled specifically.

更多信息

¥Further information

文档

¥Documentation

讨论

¥Discussions

¥Libraries