configureStore
建立 Redux store 的標準方法。它在內部使用低階 Redux 核心 createStore
方法,但會包裝它以提供良好的預設值給 store 設定,以獲得更好的開發體驗。
目的和行為
標準的 Redux store 設定通常需要多個設定項目
- 將 slice reducer 結合到根 reducer
- 建立 middleware enhancer,通常使用 thunk middleware 或其他 side effects middleware,以及可能用於開發檢查的 middleware
- 加入 Redux DevTools enhancer,並組合 enhancer
- 呼叫
createStore
傳統 Redux 使用模式通常需要複製貼上數十行樣板程式碼才能達成此目的。
Redux Toolkit 的 configureStore
簡化了設定流程,為您執行所有工作。呼叫 configureStore
一次將
- 呼叫
combineReducers
將您的 slice reducer 合併到根 reducer 函式 - 加入 thunk middleware 並呼叫
applyMiddleware
- 在開發過程中,自動加入更多 middleware 來檢查常見錯誤,例如意外變更狀態
- 自動設定 Redux DevTools Extension 連線
- 呼叫
createStore
使用該根 reducer 和那些組態選項建立 Redux store
與原始 createStore
相比,configureStore
還提供改善的 API 和使用模式,它接受 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。
如果它是一個 slice reducer 物件,例如 {users : usersReducer, posts : postsReducer}
,configureStore
將自動建立根 reducer,方法是將此物件傳遞給 Redux combineReducers
工具程式。
middleware
一個會接收 getDefaultMiddleware
作為其參數的回呼,並應傳回一個 middleware 陣列。
如果提供此選項,它應傳回您要加入 store 的所有 middleware 函式。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