菜单

Middleware 和 Enhancers

相关源文件

本文档涵盖了 Redux 的核心扩展机制:中间件和 store 增强器。两者都允许您自定义 Redux 的行为,但在架构中扮演着不同的角色。中间件在分发的 action 到达 reducer 之前对其进行拦截,而增强器则修改 store 本身。有关在 TypeScript 中使用它们的更多信息,请参阅TypeScript 集成

什么是中间件和增强器?

中间件和增强器是扩展 Redux 功能超出其核心能力的主要方式。它们使 Redux 能够处理副作用、异步操作、日志记录以及其他不属于 Redux 核心状态管理模型的功能。

Sources: docs/api/applyMiddleware.md12-30 docs/api/Store.md56-61 docs/faq/DesignDecisions.md67-71

中间件:概述与用途

中间件提供了一个第三方扩展点,位于 action 被分发与它到达 reducer 之间。它在 store 的 dispatch 方法周围形成一个管道,允许您在 action 被分发时添加自定义行为。

中间件特别适用于

  1. 处理副作用(API 调用、日志记录等)
  2. 转换 action
  3. 有条件地分发 action
  4. 支持非标准 action 类型(函数、Promise)

Sources: docs/api/applyMiddleware.md12-23 docs/usage/side-effects-approaches.mdx34-42

中间件签名

中间件签名使用柯里化来创建函数管道。这种设计允许中间件包装 dispatch 方法,并访问 store 和链中的下一个中间件。

中间件具有此签名

Sources: docs/api/applyMiddleware.md30-31 docs/faq/DesignDecisions.md67-115

nextdispatch 的区别

在中间件函数中

  • next 指的是链中的下一个中间件(如果是最后一个中间件,则指实际的 store.dispatch)
  • dispatch 指的是 store 的 dispatch 方法,它会再次从中间件链的开头开始处理 action

当您想在中间件内部分发新的 action 时,这个区别很重要

  • 使用 next(someNewAction) 会绕过所有之前的中间件
  • 使用 dispatch(someNewAction) 会使 action 通过整个中间件管道

Sources: docs/faq/StoreSetup.md16-17 docs/faq/DesignDecisions.md118-157

将中间件与 applyMiddleware 结合使用

从旧版 Redux 迁移指南:applyMiddleware 函数是将中间件添加到 Redux store 的方式。它是一个 store 增强器,允许您将多个中间件函数组合在一起。

在现代 Redux 应用程序中(使用 Redux Toolkit),中间件是使用 configureStore 函数配置的,该函数会自动设置常用中间件。

Sources: docs/api/applyMiddleware.md36-225 docs/usage/migrating-to-modern-redux.mdx75-117

常见中间件示例

Thunk 中间件

Redux Thunk 是用于处理异步逻辑的最广泛使用的中间件之一。它允许 action creator 返回函数而不是普通的 action 对象。这些函数(thunks)接收 dispatchgetState 作为参数。

thunk 的使用示例

Sources: docs/api/applyMiddleware.md73-202 docs/faq/Actions.md67-123

日志中间件

一个简单的中间件示例是一个日志记录器,它打印 action 和状态更改。

Sources: docs/api/applyMiddleware.md44-68

Store 增强器

Store 增强器是高阶函数,它们组合 store 创建器以返回一个新的、增强的 store 创建器。它们比中间件更强大,允许您修改 store 的任何方面,而不仅仅是 dispatch 方法。

Sources: docs/api/applyMiddleware.md229-232 docs/faq/DesignDecisions.md67-71

作为增强器的 applyMiddleware

applyMiddleware 函数本身就是一个 store 增强器。它接受您的中间件函数,并返回一个修改 store dispatch 方法的 store 增强器。

当应用于 store 创建过程时,applyMiddleware 将 store 的 dispatch 方法替换为一个新函数,该函数在到达原始 dispatch 之前通过中间件链处理 action。

Sources: docs/api/applyMiddleware.md2-10 docs/api/applyMiddleware.md229-232

组合多个增强器

如果您需要将多个增强器应用于您的 store,可以使用 compose 函数将它们组合起来。

在 Redux Toolkit 中,增强器可以添加到 configureStore 中。

Sources: docs/api/compose.md33-47 docs/usage/migrating-to-modern-redux.mdx119-201

编写自定义中间件

自定义中间件遵循标准中间件模式。

自定义中间件的最佳实践

  1. 让中间件专注于特定关注点:每个中间件都应处理一个特定任务。
  2. 返回 next(action) 的结果:这确保了中间件链的正确流程。
  3. 检查 action 类型:为了性能,只处理您关心的 action。
  4. 优雅地处理错误:使用 try/catch 来防止 dispatch 管道崩溃。

Sources: docs/usage/WritingCustomMiddleware.md1-140

中间件执行的时机和顺序

中间件的应用顺序很重要。

在排序中间件时,请考虑以下因素:

  • 转换 action 的中间件应该排在前面。
  • 日志记录中间件通常放在最后,以便在转换后查看 action。
  • 像 redux-thunk 这样的异步中间件应该放在期望普通 action 的中间件之前。

Sources: docs/usage/WritingCustomMiddleware.md117-139 docs/api/applyMiddleware.md206-209

性能考量

  1. 中间件可能会影响性能:每个中间件都会给每个 action 增加处理开销。
  2. 批量更新:对于高频率的 dispatch,考虑使用 redux-batch 等库来批量处理 action。
  3. 选择性处理:让中间件检查 action 类型,以跳过处理不相关的 action。

Sources: docs/faq/Performance.md116-154

中间件与增强器:何时使用?

在以下情况下使用中间件:

  • 处理或转换 action
  • 处理副作用,例如 API 调用
  • 记录 action 和状态更改
  • 支持异步逻辑

在以下情况下使用增强器:

  • 修改 store 本身(而不仅仅是 dispatch)
  • 为 store 添加新功能
  • 与复杂的外部系统集成
  • 对 Redux 的工作方式进行根本性更改

经验法则:对于大多数自定义,请从中间件开始,仅在中间件不足的更高级情况下使用增强器。

Sources: docs/api/applyMiddleware.md229-232 docs/faq/DesignDecisions.md67-115

根据您的用例,以下是推荐的中间件选项:

用例推荐的中间件替代方案
API 调用和数据获取RTK QuerycreateAsyncThunk
简单异步逻辑Redux Thunk-
复杂异步工作流Redux SagaRedux Observable
日志记录redux-logger自定义日志中间件
持久连接自定义 socket 中间件-
本地存储持久化redux-persist-

Sources: docs/usage/side-effects-approaches.mdx52-61 docs/faq/CodeStructure.md153-169

与 TypeScript 结合使用

当您在 TypeScript 中使用中间件时,需要正确地为中间件函数定义类型。

有关在 TypeScript 中使用中间件的更多详细信息,请参阅TypeScript 集成

Sources: docs/usage/UsageWithTypescript.md256-294

结论

中间件和增强器是强大的扩展机制,使 Redux 灵活且适应复杂的应用程序需求。中间件适用于大多数自定义需求,特别是处理副作用和异步逻辑,而增强器则在需要时提供更深层次的集成。

对于现代 Redux 应用程序,Redux Toolkit 的 configureStore 简化了中间件和增强器的设置,提供了良好的默认配置,同时仍然允许自定义。