本文へスキップ

configureStore

Reduxストアを作成するための標準的な方法です。内部的には低レベルのReduxコア`createStore`メソッドを使用していますが、ストア設定に適切なデフォルト値を提供することで、より良い開発エクスペリエンスを実現するためにラップされています。

目的と動作

標準的なReduxストアの設定には、通常、複数の構成要素が必要です。

  • スライスReducerをルートReducerに結合する
  • ミドルウェアエンハンサーを作成します。通常はthunkミドルウェアまたはその他の副作用ミドルウェア、そして開発チェックに使用される可能性のあるミドルウェアも含まれます。
  • Redux DevToolsエンハンサーを追加し、エンハンサーをまとめて合成します。
  • `createStore`を呼び出します。

従来のReduxの使用パターンでは、これを実現するために数十行ものコピー&ペーストされたボイラープレートコードが必要でした。

Redux Toolkitの`configureStore`は、その設定プロセスを簡素化し、すべての作業を自動的に行います。`configureStore`を一度呼び出すと、

  • `combineReducers`を呼び出して、スライスReducerをルートReducer関数に結合します。
  • thunkミドルウェアを追加し、`applyMiddleware`を呼び出します。
  • 開発環境では、状態の意図しない変更など、よくある間違いをチェックするためのミドルウェアを自動的に追加します。
  • Redux DevTools Extension接続を自動的に設定します。
  • そのルートReducerと構成オプションを使用して、`createStore`を呼び出してReduxストアを作成します。

`configureStore`は、`reducer`、`preloadedState`、`middleware`、`enhancers`、`devtools`の各フィールドを名前付きで受け入れること、そしてTS型の推論が大幅に向上していることなど、元の`createStore`と比較して改善されたAPIと使用方法を提供します。

パラメーター

`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`

単一の関数の場合、ストアのルートReducerとして直接使用されます。

`{users : usersReducer, posts : postsReducer}`のようなスライスReducerのオブジェクトの場合、`configureStore`はこのオブジェクトをReduxの`combineReducers`ユーティリティに渡して、自動的にルートReducerを作成します。

`middleware`

`getDefaultMiddleware`を引数として受け取り、ミドルウェアの配列を返すコールバックです。

このオプションが指定されている場合、ストアに追加するすべてのミドルウェア関数を返す必要があります。`configureStore`は、それらを`applyMiddleware`に自動的に渡します。

指定されていない場合、`configureStore`は`getDefaultMiddleware`を呼び出し、返されたミドルウェア関数の配列を使用します。

`middleware`パラメーターの動作の詳細と、デフォルトで追加されるミドルウェアのリストについては、`getDefaultMiddleware`のドキュメントページを参照してください。

タプル

TypeScriptユーザーは、(既にタプルである`getDefaultMiddleware`の結果を使用していない場合)より良い推論のために`Tuple`インスタンスを使用する必要があります。

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

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

JavaScriptのみのユーザーは、必要に応じてプレーンな配列を使用できます。

`devTools`

ブール値の場合、`configureStore`がRedux DevToolsブラウザ拡張機能のサポートを自動的に有効にするかどうかを示すために使用されます。

オブジェクトの場合、DevTools Extensionが有効になり、オプションオブジェクトが`composeWithDevtools()`に渡されます。使用可能な特定のオプションのリストについては、DevTools Extensionのドキュメントの`EnhancerOptions`を参照してください。

デフォルトは`true`です。

`trace`

Redux DevTools Extensionは最近、各アクションがどこでディスパッチされたかを正確に示すアクションスタックトレースを表示するスタックトレースの表示機能を追加しました。トレースのキャプチャは多少オーバーヘッドを追加する可能性があるため、DevTools Extensionでは、`'trace'`引数を設定することで、アクションスタックトレースのキャプチャを有効にするかどうかをユーザーが設定できます。`true`またはオブジェクトを渡してDevToolsを有効にすると、`configureStore`は開発モードでのみアクションスタックトレースのキャプチャを有効にするようにデフォルト設定されます。

`preloadedState`

Reduxの`createStore`関数に渡されるオプションの初期状態値です。

`enhancers`

エンハンサーの配列をカスタマイズするためのコールバック関数です。

このコールバックによって返されたエンハンサーはReduxの`compose`関数に渡され、合成されたエンハンサーが`createStore`に渡されます。

DevTools

これは、`configureStore`によって既に処理されているため、Redux DevTools Extensionの`composeWithDevTools`を含めるべきではありません。

例:`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を使用する場合は、`getDefaultEnhancers`の型がその結果に依存するため、エンハンサーオプションの前に`middleware`オプションを指定する必要があります。

タプル

TypeScriptユーザーは、(既にタプルである`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