getDefaultMiddleware

返回包含一个默认中间件列表的数组

预期用法

默认情况下,configureStore 自动把中间件加到 Redux store 设置中。

const store = configureStore({
reducer: rootReducer
})
// 中间件被加到 Store,因为中间件列表不是自定义的。

如果你想自定义中间件列表,你可以为 configureStore 提供一个中间件函数数组:

const store = configureStore({
reducer: rootReducer,
middleware: [thunk, logger]
})
// Store 在此有 thunk 和 logger 中间件

然而,当你提供了 middleware 选项,你要为定义 所有 你想要添加到 store 的中间件负责。configureStore 不会添加任何额外超出被列出的中间件。

如果你想添加自定义的中间件,getDefaultMiddleware 会派得上用场,但是你仍然想要默认中间件被添加进来:

import { configureStore } from '@reduxjs/toolkit'
import logger from 'redux-logger'
import rootReducer from './reducer'
const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
})
// Store 包含所有被添加进来的默认中间价,再 _加上_ logger 中间件

使用 .concat(...).prepend(...) 这种链式调用方法是而不是数组扩展运算符是更优的选择,因为后者会再某些情况下会丢失重要的类型信息。

getDefaultMiddleware 导入

尽在上一个例子中所示的 configureStore 回调表示法是使用 getDefaultMiddleware 的最佳方案,它也可以独立于 'configureStore' 被单独导入使用:

import { getDefaultMiddleware } from '@reduxjs/toolkit'
interface State {
// ...
}
const middlewares = getDefaultMiddleware<State>()

使用回调表示法的好处是 State 类型已经被提前绑定了,因此可能能避免在手动指定泛型的时候的循环类型引用。

被包含的默认中间件

开发环境

Redux工具包 的其中一个目标是提供有自己想法的默认设置和避免常见的错误。作为其中的一部分,getDefaultMiddleware 包括了一些只在开发过程中加入的中间件,以提供两种常见问题的运行时检查方案:

  • Immutability check middleware: 深度对比 mutations 的状态值。它可以检测到派发过程中 reducers 的 mutations,还有发生在若干派发之间的 mutations (例如在组件或者 selector里)。当某个 mutation 被检测到时,它会抛出一个错误并且会提示该 mutated 的值在状态树里的关键路径 (Forked from redux-immutable-state-invariant)。

  • Serializability check middleware: 一个专门为 Redux工具包 创建的自定义中间件。与 immutable-state-invariant 概念类似,但是深度检查状态树以及针对不可被序列化的值,例如函数,Promises,Symbols 和其他非 JS 数值的操作。当一个不可被序列化的值被检测到的时候,控制台会打印出一个错误,带有该不可被序列化值的关键路径。

除了这些开发环境的中间件工具意外,它也默认添加了 redux-thunk,因为 thunks 是 Redux 的推荐处理副作用的中间件。

现在的返回值是:

const middleware = [thunk, immutableStateInvariant, serializableStateInvariant]

生产环境

现在的返回值是:

const middleware = [thunk]

自定义被包含的中间件

getDefaultMiddleware 接收一个能用两种方式自定义中间件的选项对象:

  • 每一个中间件能把结果数组排除掉,通过传递响应的字段一个 false

  • 通过传递相应字段的选项对象,每一个中间件能够自定义自己的选项

这个例子展示了如何排除序列化状态检查中间件,还有给 thunk 中间件的 “额外参数” 传递一个具体的值:

import { configureStore } from '@reduxjs/toolkit'
import rootReducer from './reducer'
import { myCustomApiService } from './api'
const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
thunk: {
extraArgument: myCustomApiService,
},
serializableCheck: false,
}),
})

API 参考

interface ThunkOptions<E = any> {
extraArgument: E
}
interface ImmutableStateInvariantMiddlewareOptions {
// 查阅 "Immutability Middleware" 页面获取定义解释
}
interface SerializableStateInvariantMiddlewareOptions {
// 查阅 "Serializability Middleware" 页面获取定义解释
}
interface GetDefaultMiddlewareOptions {
thunk?: boolean | ThunkOptions
immutableCheck?: boolean | ImmutableStateInvariantMiddlewareOptions
serializableCheck?: boolean | SerializableStateInvariantMiddlewareOptions
}
function getDefaultMiddleware<S = any>(
options: GetDefaultMiddlewareOptions = {}
): Middleware<{}, S>[]