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
相比,它接受 reducer
、preloadedState
、middleware
、enhancers
和 devtools
的命名字段,以及更好的 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 的用户可以自由使用普通数组,如果需要的话。
用法
基本示例
- TypeScript
- 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
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