跳至主要内容

Redux 常见问题解答:操作

目录

操作

为什么 type 应该是一个字符串?为什么我的操作类型应该是常量?

与状态一样,可序列化动作使 Redux 的一些定义功能成为可能,例如时间旅行调试以及记录和重放动作。使用类似于 `Symbol` 的 `type` 值或使用 `instanceof` 检查动作本身会破坏这一点。字符串是可序列化的,并且易于自描述,因此是更好的选择。请注意,如果动作旨在供中间件使用,则在动作中使用 `Symbol`、`Promise` 或其他不可序列化值是可以的。动作只需要在实际到达存储并传递给 reducer 时才可序列化。

由于性能原因,我们无法可靠地强制执行可序列化动作,因此 Redux 只检查每个动作是否为普通对象,以及 `type` 是否为字符串。其余部分由您决定,但您可能会发现保持所有内容可序列化有助于调试和重现问题。

封装和集中化常用代码片段是编程中的一个关键概念。虽然在任何地方手动创建动作对象以及手动编写每个 `type` 值当然是可以的,但定义可重用常量可以使代码维护更容易。如果您将常量放在单独的文件中,您可以 检查您的 `import` 语句是否存在拼写错误,这样您就不会意外使用错误的字符串。

更多信息

文档

讨论

reducer 和动作之间总是存在一对一映射吗?

不,我们建议您编写独立的小型 reducer 函数,每个函数负责更新状态的特定切片。我们称这种模式为“reducer 组合”。给定的操作可以由所有、部分或没有 reducer 函数处理。这使组件与实际数据更改脱钩,因为一个操作可能会影响状态树的不同部分,并且组件无需了解这一点。一些用户选择将它们更紧密地绑定在一起,例如“ducks”文件结构,但默认情况下绝对没有一对一的映射,并且您应该在任何时候想要在多个 reducer 中处理操作时摆脱这种范式。

更多信息

文档

讨论

如何表示“副作用”,例如 AJAX 调用?为什么我们需要像“action creator”、“thunk”和“中间件”这样的东西来执行异步行为?

这是一个漫长而复杂的话题,关于如何组织代码以及应该使用哪些方法,存在着各种各样的观点。

任何有意义的 Web 应用程序都需要执行复杂的逻辑,通常包括异步工作,例如发出 AJAX 请求。该代码不再仅仅是其输入的函数,与外部世界的交互被称为“副作用”

Redux 受到函数式编程的启发,并且开箱即用,没有地方执行副作用。特别是,reducer 函数必须始终是(state, action) => newState的纯函数。但是,Redux 的中间件使得拦截已分派的 action 并围绕它们添加额外的复杂行为成为可能,包括副作用。

一般来说,Redux 建议带有副作用的代码应该是 action 创建过程的一部分。虽然该逻辑可以在 UI 组件内部执行,但通常将该逻辑提取到可重用的函数中是有意义的,这样就可以从多个地方调用相同的逻辑——换句话说,一个 action creator 函数。

最简单、最常见的做法是添加 Redux Thunk 中间件,它允许您编写具有更复杂异步逻辑的动作创建器。另一种广泛使用的方法是 Redux Saga,它允许您使用生成器编写更像同步的代码,并且可以像 Redux 应用程序中的“后台线程”或“守护进程”一样工作。另一种方法是 Redux Loop,它通过允许您的 reducer 声明对状态更改的副作用并单独执行它们来反转该过程。除此之外,还有 *许多* 其他社区开发的库和想法,每个库和想法都有自己关于如何管理副作用的看法。

更多信息

文档

文章

讨论

我应该使用哪个异步中间件?您如何决定在 thunk、传奇、可观察对象或其他东西之间进行选择?

许多可用的异步/副作用中间件,但最常用的中间件是 redux-thunkredux-sagaredux-observable。这些是不同的工具,具有不同的优势、劣势和用例。

一般来说

  • Thunks 最适合处理复杂的同步逻辑(尤其是需要访问整个 Redux 存储状态的代码)和简单的异步逻辑(例如基本的 AJAX 调用)。使用 `async/await`,对于一些更复杂的基于 Promise 的逻辑,使用 thunks 也是合理的。
  • Sagas 最适合处理复杂的异步逻辑和解耦的“后台线程”型行为,尤其是在需要监听分派的 action(这是 thunks 做不到的)时。它们需要熟悉生成器函数和 `redux-saga` 的“效果”操作符。
  • Observables 解决与 sagas 相同的问题,但依赖于 RxJS 来实现异步行为。它们需要熟悉 RxJS API。

我们建议大多数 Redux 用户应该从 thunks 开始,如果他们的应用程序确实需要处理更复杂的异步逻辑,则可以稍后添加额外的副作用库,例如 sagas 或 observables。

由于 sagas 和 observables 具有相同的用例,应用程序通常会使用其中一个,而不是两者都使用。但是,请注意,**将 thunks 与 sagas 或 observables 结合使用绝对没问题**,因为它们解决的是不同的问题。

文章

讨论

我应该从一个 action creator 中连续分派多个 action 吗?

对于如何构建 action 没有特定的规则。使用 Redux Thunk 之类的异步中间件确实可以实现以下场景,例如连续分派多个不同的但相关的 action,分派 action 来表示 AJAX 请求的进度,根据状态有条件地分派 action,甚至分派 action 并立即检查更新后的状态。

一般来说,请询问这些操作是否相关但独立,或者是否应该实际表示为一个操作。根据您的实际情况做出最合理的决定,但请尽量平衡 reducer 的可读性和操作日志的可读性。例如,包含整个新状态树的操作会使您的 reducer 变成一行代码,但缺点是您将无法了解更改发生的原因,因此调试变得非常困难。另一方面,如果您在循环中发出操作以保持它们粒度,则表明您可能需要引入一种以不同方式处理的新操作类型。

在您关心性能的地方,请尽量避免在同一时间内连续多次分派。有一些插件和方法可以批量分派操作。

更多信息

文档

文章

讨论