跳至主要内容

configureStore

创建 Redux 商店的标准方法。它在内部使用低级 Redux 核心 createStore 方法,但对其进行包装以提供商店设置的良好默认值,从而获得更好的开发体验。

目的和行为

标准 Redux 商店设置通常需要多个配置部分

  • 将切片 reducer 组合成根 reducer
  • 创建中间件增强器,通常使用 thunk 中间件或其他副作用中间件,以及可能用于开发检查的中间件
  • 添加 Redux DevTools 增强器,并将增强器组合在一起
  • 调用 createStore

传统的 Redux 使用模式通常需要几十行复制粘贴的样板代码才能实现这一点。

Redux Toolkit 的 configureStore 简化了此设置过程,它为您完成所有这些工作。一次调用 configureStore

  • 调用 combineReducers 将您的切片 reducer 组合成根 reducer 函数
  • 添加 thunk 中间件并调用 applyMiddleware
  • 在开发环境中,自动添加更多中间件以检查常见的错误,例如意外地修改状态
  • 自动设置 Redux DevTools Extension 连接
  • 调用 createStore 使用根 reducer 和这些配置选项创建 Redux store

configureStore 还提供了一个改进的 API 和使用模式,与原始的 createStore 相比,它接受 reducerpreloadedStatemiddlewareenhancersdevtools 的命名字段,以及更好的 TS 类型推断。

参数

configureStore 接受一个单一的配置对象参数,包含以下选项


interface ConfigureStoreOptions<
S = any,
A extends Action = UnknownAction,
M extends Tuple<Middlewares<S>> = Tuple<Middlewares<S>>
E extends Tuple<Enhancers> = Tuple<Enhancers>,
P = S
> {
/**
* A single reducer function that will be used as the root reducer, or an
* object of slice reducers that will be passed to `combineReducers()`.
*/
reducer: Reducer<S, A, P> | ReducersMapObject<S, A, P>

/**
* An array of Redux middleware to install. If not supplied, defaults to
* the set of middleware returned by `getDefaultMiddleware()`.
*/
middleware?: ((getDefaultMiddleware: CurriedGetDefaultMiddleware<S>) => M) | M

/**
* Whether to enable Redux DevTools integration. Defaults to `true`.
*
* Additional configuration can be done by passing Redux DevTools options
*/
devTools?: boolean | DevToolsOptions

/**
* The initial state, same as Redux's createStore.
* You may optionally specify it to hydrate the state
* from the server in universal apps, or to restore a previously serialized
* user session. If you use `combineReducers()` to produce the root reducer
* function (either directly or indirectly by passing an object as `reducer`),
* this must be an object with the same shape as the reducer map keys.
*/
preloadedState?: P

/**
* The store enhancers to apply. See Redux's `createStore()`.
* All enhancers will be included before the DevTools Extension enhancer.
* If you need to customize the order of enhancers, supply a callback
* function that will receive the getDefaultEnhancers,
* and should return a new array (such as `getDefaultEnhancers().concat(offline)`).
* If you only need to add middleware, you can use the `middleware` parameter instead.
*/
enhancers?: (getDefaultEnhancers: GetDefaultEnhancers<M>) => E | E
}

function configureStore<
S = any,
A extends Action = UnknownAction,
M extends Tuple<Middlewares<S>> = Tuple<Middlewares<S>>
E extends Tuple<Enhancers> = Tuple<Enhancers>,
P = S
>(options: ConfigureStoreOptions<S, A, M, E, P>): EnhancedStore<S, A, M, E>

reducer

如果这是一个单一函数,它将直接用作 store 的根 reducer。

如果它是一个切片 reducer 的对象,例如 {users : usersReducer, posts : postsReducer}configureStore 将自动创建根 reducer,通过将此对象传递给 Redux combineReducers 工具

middleware

一个回调函数,它将接收 getDefaultMiddleware 作为参数,并应该返回一个中间件数组。

如果提供了此选项,它应该返回所有你想要添加到 store 的中间件函数。configureStore 将自动将它们传递给 applyMiddleware

如果没有提供,configureStore 将调用 getDefaultMiddleware 并使用它返回的中间件函数数组。

有关 middleware 参数的工作原理以及默认添加的中间件列表的更多详细信息,请参阅 getDefaultMiddleware 文档页面

元组

Typescript 用户需要使用 Tuple 实例(如果未使用 getDefaultMiddleware 结果,该结果已经是 Tuple),以便更好地推断。

import { configureStore, Tuple } from '@reduxjs/toolkit'

configureStore({
reducer: rootReducer,
middleware: () => new Tuple(additionalMiddleware, logger),
})

仅使用 Javascript 的用户可以自由使用普通数组,如果需要的话。

devTools

如果这是一个布尔值,它将用于指示 configureStore 是否应该自动启用对 Redux DevTools 浏览器扩展 的支持。

如果它是一个对象,则将启用 DevTools 扩展,并且选项对象将传递给 composeWithDevtools()。有关可用选项的列表,请参阅 DevTools 扩展文档的 EnhancerOptions

默认为 true

trace

Redux DevTools 扩展最近添加了 对显示操作堆栈跟踪的支持,这些跟踪显示了每个操作的具体派发位置。捕获跟踪可能会增加一些开销,因此 DevTools 扩展允许用户通过 设置 'trace' 参数 来配置是否捕获操作堆栈跟踪。如果通过传递 true 或一个对象来启用 DevTools,则 configureStore 将默认在开发模式下启用捕获操作堆栈跟踪。

preloadedState

可选的初始状态值,传递给 Redux 的 createStore 函数。

enhancers

一个回调函数,用于自定义增强器数组。

此回调函数返回的增强器将传递给 Redux 的 compose 函数,组合后的增强器将传递给 createStore

开发者工具

应该包含 Redux DevTools Extension 的 composeWithDevTools,因为 configureStore 已经处理了它。

例如:enhancers: () => new Tuple(offline) 将导致最终的设置 [offline, devToolsExtension]

如果没有提供,configureStore 将调用 getDefaultEnhancers 并使用它返回的增强器数组(包括使用指定中间件的 applyMiddleware)。

如果你想添加或自定义默认增强器,你可以传递一个回调函数,该函数将接收 getDefaultEnhancers 作为参数,并应该返回一个增强器数组。

例如:enhancers: (defaultEnhancers) => defaultEnhancers.prepend(offline) 将导致最终的设置 [offline, applyMiddleware, devToolsExtension]

有关 enhancer 参数的工作原理以及默认添加的增强器列表的更多详细信息,请参阅 getDefaultEnhancers 文档页面

中间件

如果你不使用 getDefaultEnhancers 而是返回一个数组,applyMiddleware 增强器不会被使用。

如果提供了任何中间件(或保留为默认值)但未包含在最终的增强器列表中,configureStore 将在控制台中发出警告。

// warns - middleware customised but not included in final enhancers
configureStore({
reducer,
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger)
enhancers: [offline(offlineConfig)],
})

// fine - default enhancers included
configureStore({
reducer,
enhancers: (getDefaultEnhancers) => getDefaultEnhancers().concat(offline(offlineConfig)),
})

// also allowed
configureStore({
reducer,
middleware: () => [],
enhancers: () => [offline(offlineConfig)],
})

请注意,如果使用 Typescript,middleware 选项需要在增强器选项之前提供,因为 getDefaultEnhancers 的类型取决于其结果。

元组

Typescript 用户需要使用 Tuple 实例(如果未使用 getDefaultEnhancer 结果,该结果已经是 Tuple),以获得更好的推断。

import { configureStore, Tuple } from '@reduxjs/toolkit'

configureStore({
reducer: rootReducer,
enhancers: () => new Tuple(offline),
})

仅使用 Javascript 的用户可以自由使用普通数组,如果需要的话。

用法

基本示例

import { configureStore } from '@reduxjs/toolkit'

import rootReducer from './reducers'

const store = configureStore({ reducer: rootReducer })
// The store now has redux-thunk added and the Redux DevTools Extension is turned on

完整示例

// file: todos/todosReducer.ts noEmit
import type { Reducer } from '@reduxjs/toolkit'
declare const reducer: Reducer<{}>
export default reducer

// file: visibility/visibilityReducer.ts noEmit
import type { Reducer } from '@reduxjs/toolkit'
declare const reducer: Reducer<{}>
export default reducer

// file: store.ts
import { configureStore } from '@reduxjs/toolkit'

// We'll use redux-logger just as an example of adding another middleware
import logger from 'redux-logger'

// And use redux-batched-subscribe as an example of adding enhancers
import { batchedSubscribe } from 'redux-batched-subscribe'

import todosReducer from './todos/todosReducer'
import visibilityReducer from './visibility/visibilityReducer'

const reducer = {
todos: todosReducer,
visibility: visibilityReducer,
}

const preloadedState = {
todos: [
{
text: 'Eat food',
completed: true,
},
{
text: 'Exercise',
completed: false,
},
],
visibilityFilter: 'SHOW_COMPLETED',
}

const debounceNotify = _.debounce((notify) => notify())

const store = configureStore({
reducer,
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
devTools: process.env.NODE_ENV !== 'production',
preloadedState,
enhancers: (getDefaultEnhancers) =>
getDefaultEnhancers({
autoBatch: false,
}).concat(batchedSubscribe(debounceNotify)),
})

// The store has been created with these options:
// - The slice reducers were automatically passed to combineReducers()
// - redux-thunk and redux-logger were added as middleware
// - The Redux DevTools Extension is disabled for production
// - The middleware, batched subscribe, and devtools enhancers were composed together