configureStore reducer parameter
The reducer parameter can be either a single reducer function of type Reducer<S, A, P> or an object of slice reducers of type ReducersMapObject<S, A, P>. If a single function is provided, it is used directly as the root reducer. If an object of slice reducers is provided, configureStore automatically passes it to Redux's combineReducers utility to create the root reducer.
configureStore middleware parameter
The middleware parameter is optional and can be either a callback function or an array. If a callback is provided, it receives getDefaultMiddleware as an argument and should return a middleware array M. The callback must return all middleware functions to be added to the store. If not provided, configureStore calls getDefaultMiddleware and uses its return value. When using TypeScript, if returning a custom array (not getDefaultMiddleware result), a Tuple instance must be used for better inference.
configureStore devTools parameter
The devTools parameter is optional and defaults to true. If it is a boolean, it indicates whether configureStore should automatically enable support for the Redux DevTools browser extension. If it is an object, the DevTools Extension is enabled and the options object is passed to composeWithDevtools(). The Redux DevTools options object is of type DevToolsOptions.
configureStore duplicateMiddlewareCheck parameter
The duplicateMiddlewareCheck parameter is optional and defaults to true. When enabled, the store checks the final middleware array for duplicate middleware references. This catches issues like accidentally adding the same RTK Query API middleware twice.
configureStore preloadedState parameter
The preloadedState parameter is optional and has type P (which defaults to S, the state type). It is the initial state value passed to Redux's createStore function. It can be used to hydrate the state from the server in universal apps or to restore a previously serialized user session. If combineReducers produces the root reducer, preloadedState must be an object with the same shape as the reducer map keys.
configureStore enhancers parameter
The enhancers parameter is optional and can be either a callback function or an array. Enhancers can be used to customize the store setup. If a callback is provided, it receives getDefaultEnhancers as its argument and should return an enhancer array E of type Tuple<Enhancers>. All enhancers are included before the DevTools Extension enhancer. If a callback is not provided, configureStore calls getDefaultEnhancers and uses the array it returns. When using TypeScript with a custom array, a Tuple instance must be used for better inference.
configureStore ConfigureStoreOptions interface full specification
ConfigureStoreOptions is a generic interface with properties: reducer (required, type Reducer<S, A, P> | ReducersMapObject<S, A, P>), middleware (optional, type ((getDefaultMiddleware: CurriedGetDefaultMiddleware<S>) => M) | M), devTools (optional, type boolean | DevToolsOptions, defaults to true), duplicateMiddlewareCheck (optional, type boolean, defaults to true), preloadedState (optional, type P), and enhancers (optional, type ((getDefaultEnhancers: GetDefaultEnhancers<M>) => E) | E).
configureStore action stack traces in DevTools
When DevTools are enabled by passing true or an object to the devTools parameter, configureStore defaults to enabling capturing of action stack traces in development mode only. This allows the Redux DevTools Extension to show exactly where each action was dispatched.
configureStore enhancers ordering and middleware warning
When providing custom enhancers without using getDefaultEnhancers, the applyMiddleware enhancer will not be automatically included. configureStore will warn in console if any middleware are provided (or left as default) but not included in the final list of enhancers. When using TypeScript, the middleware option must be provided before the enhancers option, as the type of getDefaultEnhancers depends on the middleware result.
configureStore automatic setup steps
One call to configureStore performs these automatic steps: calls combineReducers to combine slice reducers into the root reducer function, adds the thunk middleware and calls applyMiddleware, automatically adds development middleware to check for common mistakes like accidentally mutating state, automatically sets up the Redux DevTools Extension connection, and calls createStore to create a Redux store with the root reducer and configuration options.
configureStore basic example
Basic usage of configureStore with a single root reducer: import { configureStore } from '@reduxjs/toolkit'; import rootReducer from './reducers'; const store = configureStore({ reducer: rootReducer }); This creates a store with redux-thunk added and Redux DevTools Extension turned on automatically.
configureStore full example with multiple reducers, middleware, preloaded state, and enhancers
Full example showing configureStore with multiple features: import { configureStore } from '@reduxjs/toolkit'; import logger from 'redux-logger'; 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)) }); This example demonstrates using slice reducers, adding custom middleware, conditionally enabling DevTools, providing preloaded state, and customizing enhancers.
Infer RootState type from store
RootState type can be inferred from the store using: export type RootState = ReturnType<typeof store.getState>
configureStore accepts reducer parameter
configureStore accepts a reducer function as a named argument. It automatically sets up the store with good default settings.
configureStore example with empty reducer
Example: import { configureStore } from '@reduxjs/toolkit'; export const store = configureStore({ reducer: {} });
configureStore automatically sets up Redux DevTools
configureStore automatically configures the Redux DevTools extension so that you can inspect the store while developing.
Infer AppDispatch type from store
AppDispatch type can be inferred from the store using: export type AppDispatch = typeof store.dispatch
React Redux type definitions via @types/react-redux
React Redux has its type definitions in a separate '@types/react-redux' typedefs package on NPM. As of React Redux v7.2.3, the react-redux package has a dependency on @types/react-redux, so the type definitions are automatically installed with the library. Otherwise, they must be manually installed with 'npm install @types/react-redux'.
Redux Toolkit is written in TypeScript with built-in type definitions
Redux Toolkit is already written in TypeScript, so its TS type definitions are built in and do not require separate installation.
Extract RootState type from store with ReturnType
RootState type should be extracted from the store using 'export type RootState = ReturnType<typeof store.getState>'. This infers the type from the store itself and ensures it correctly updates as state slices or middleware settings are modified. The type should be exported from the store setup file such as 'app/store.ts'.
Extract AppDispatch type from store dispatch property
AppDispatch type should be extracted from the store using 'export type AppDispatch = typeof store.dispatch'. This captures the store's dispatch type including thunk middleware. The type should be exported from the store setup file such as 'app/store.ts'.
Create typed useDispatch hook with withTypes method
Create a typed version of useDispatch in a separate hooks file (e.g., 'app/hooks.ts') using 'export const useAppDispatch = useDispatch.withTypes<AppDispatch>()'. This ensures the default Dispatch type knows about thunks and prevents circular import issues since hooks are actual variables, not types.
Create typed useSelector hook with withTypes method
Create a typed version of useSelector in a separate hooks file (e.g., 'app/hooks.ts') using 'export const useAppSelector = useSelector.withTypes<RootState>()'. This saves the need to type '(state: RootState)' every time useSelector is used and avoids circular import dependency issues.
configureStore does not require additional typings
Using configureStore does not require any additional manual typings. Instead, extract RootState and AppDispatch types from the store itself so they automatically update as state or middleware changes.
Adding RTK Query service to Redux store
An RTK Query service generates a slice reducer and custom middleware. The reducer should be added to the store's reducer configuration using the reducerPath as the key, and the middleware should be added via the middleware option: middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(pokemonApi.middleware)
configureStore.middleware must be a callback function
In Redux Toolkit 2.0, the middleware option for configureStore must be a callback function that receives getDefaultMiddleware. Passing a direct array is no longer allowed. If you want to replace all middleware, return an array from the callback. However, you should normally use getDefaultMiddleware().concat(myMiddleware) to preserve default middleware.
configureStore.enhancers must be a callback function
In Redux Toolkit 2.0, the enhancers option for configureStore must be a callback function that receives getDefaultEnhancers. You can use getDefaultEnhancers() to get the default enhancers (including the autoBatchEnhancer) and customize them, then concatenate additional enhancers.
configureStore adds autoBatchEnhancer by default
In Redux Toolkit 2.0, configureStore automatically includes the autoBatchEnhancer by default. This enhancer delays notifying subscribers when multiple low-priority actions are dispatched in a row, improving performance. You can customize this behavior through the enhancers callback by passing an options object to getDefaultEnhancers().
TypeScript requires middleware and enhancers field order
When passing both middleware and enhancers fields to configureStore, the middleware field must come first in order for TypeScript type inference to work properly.
Tuple type required for custom middleware arrays
When passing custom middleware to configureStore, you must use the Tuple type instead of a plain array to maintain strong typing of middleware. Example: configureStore({ reducer, middleware: (getDefaultMiddleware) => new Tuple(additionalMiddleware, logger) }). This same restriction applies to the enhancers field.
configureStore with callback middleware example
Example of configureStore with middleware callback:
const store = configureStore({
reducer,
middleware: (getDefaultMiddleware) => {
return getDefaultMiddleware().concat(myMiddleware)
},
})
Or to replace all middleware (not recommended):
const store = configureStore({
reducer,
middleware: (getDefaultMiddleware) => {
return [myMiddleware]
},
})
configureStore with enhancers callback example
Example of configureStore with enhancers callback:
const store = configureStore({
reducer,
enhancers: (getDefaultEnhancers) => {
return getDefaultEnhancers({
autoBatch: { type: 'tick' },
}).concat(myEnhancer)
},
})
configureStore accepts a reducer as an object or root reducer function
The reducer option in configureStore can be passed either as an object mapping slice names to slice reducers (configureStore will call combineReducers internally), or as a pre-combined root reducer function created by calling combineReducers separately.
configureStore supports custom middleware configuration
configureStore accepts a middleware option that receives getDefaultMiddleware as an argument, allowing you to customize built-in middleware behavior. You can pass options to getDefaultMiddleware such as thunk configuration with extraArgument, and serializableCheck configuration to ignore specific actions. Additional middleware can be added with concat() method.
configureStore automatically adds middleware for development-mode checks
configureStore includes automatic development-mode middleware that checks for common mistakes like accidental mutations and non-serializable values in the state.
configureStore devTools option controls Redux DevTools Extension
configureStore accepts a devTools option that can be set to false to disable Redux DevTools in production, or to an object with configuration options like stateSanitizer in development mode.
configureStore automatically includes thunk middleware and Redux DevTools
Redux Toolkit's configureStore API automatically adds the thunk middleware and sets up the Redux DevTools Extension connection without requiring manual configuration. It also automatically calls combineReducers to combine slice reducers into the root reducer and calls createStore to create the Redux store.
configureStore with middleware callback example
Example of using configureStore with custom middleware and default middleware together: `configureStore({ reducer: rootReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(loggerMiddleware), preloadedState, enhancers: (getDefaultEnhancers) => getDefaultEnhancers().concat(monitorReducersEnhancer) })`
configureStore enables Redux DevTools Extension automatically
configureStore automatically enables the Redux DevTools Extension, eliminating the need for hand-written code to check if the extension is available in the global namespace.
configureStore serializableCheck configuration
configureStore's serializability dev check middleware can be configured by passing a serializableCheck option to the middleware configuration: `middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: { ignoredActions: ['your/action/type'], ignoredActionPaths: ['meta.arg', 'payload.timestamp'], ignoredPaths: ['items.dates'] } })`
configureStore basic usage with single reducer
The simplest way to use configureStore is to pass the root reducer function as a parameter named `reducer`. Example: `const store = configureStore({ reducer: rootReducer })`
configureStore with multiple slice reducers
You can pass an object full of slice reducers to configureStore, and it will call combineReducers for you automatically. Example: `configureStore({ reducer: { users: usersReducer, posts: postsReducer } })`. Note that this only works for one level of reducers; if you want nested reducers, you must call combineReducers yourself.
configureStore default middleware
configureStore automatically adds middleware by default including redux-thunk (the most commonly used middleware for handling both synchronous and async logic), and in development mode, middleware that checks for common mistakes like mutating state or using non-serializable values.
configureStore middleware option with callback
When providing the `middleware` option to configureStore, you can use a callback notation that receives `getDefaultMiddleware` as an argument. This allows you to access the default middleware and combine it with custom middleware. If you provide the middleware argument without using the callback, configureStore will only use the middleware you've explicitly listed.
Use concat and prepend for type-safe middleware composition
When adding middleware to configureStore, use the .concat(...) and .prepend(...) methods of the Tuple returned by getDefaultMiddleware() instead of the spread operator. This prevents TypeScript from widening array types.
TypeScript version support by RTK version
Redux Toolkit follows DefinitelyTyped's policy of supporting TypeScript versions released within the past two years. As of RTK 2.11, RTK 2.x requires TypeScript 5.4 or higher, and RTK 1.9.x requires TypeScript 4.7 or higher.
Extract RootState type using combineReducers and ReturnType
To get the RootState type when using combineReducers, define the root reducer with combineReducers and then export the type using: export type RootState = ReturnType<typeof rootReducer>
Extract RootState type when passing reducers directly to configureStore
When passing slice reducers directly to configureStore() without creating a rootReducer explicitly, extract RootState using: export type RootState = ReturnType<typeof store.getState>
Extract AppDispatch type from store
To extract the Dispatch type from your store after creating it, use: export type AppDispatch = typeof store.dispatch. It is recommended to give this type the name 'AppDispatch' instead of 'Dispatch' to prevent confusion.
Create a typed useAppDispatch hook
Export a pre-typed hook for dispatch using: export const useAppDispatch = useDispatch.withTypes<AppDispatch>(). This allows reuse of the correctly typed dispatch hook throughout the application.
Middleware configuration with getDefaultMiddleware
Middleware option in configureStore accepts a callback that receives getDefaultMiddleware. Use this callback to access the tuple of default middleware, then call .prepend() and .concat() to add additional middleware while maintaining proper typing.
Use Tuple class for type-safe middleware array without getDefaultMiddleware
If skipping getDefaultMiddleware, use the Tuple class from Redux Toolkit to create a type-safe middleware array: new Tuple(additionalMiddleware, logger). Tuple extends JavaScript Array with modified typings for .concat(...) and .prepend(...).
Type middleware manually in configureStore
To manually type middleware in configureStore, use the Middleware generic type: untypedMiddleware as Middleware<(action: Action<'specialAction'>) => number, RootState>
configureStore replaces manual createStore and applyMiddleware boilerplate
Use configureStore instead of manually calling createStore, combineReducers, and applyMiddleware. configureStore automatically includes default middleware, enables Immer for immutable updates, adds dev checks, and provides the modern recommended baseline for store setup.
Provider wiring for Redux in React apps
Wrap the root of the React app with <Provider store={store}> from react-redux to make the Redux store available to all components via hooks.
Migrate from createStore to configureStore basic pattern
To migrate a legacy Redux store, replace createStore with configureStore from @reduxjs/toolkit. The reducer argument accepts an object mapping reducer names to reducer functions. Legacy thunk middleware is automatically included. Example: instead of createStore(rootReducer, applyMiddleware(thunk)), use configureStore({ reducer: { posts: postsReducer, users: usersReducer } }).
configureStore replacement can happen immediately
The store setup migration from createStore to configureStore can happen in a single step while legacy reducers continue to work unchanged. This allows gradual migration without breaking existing functionality.
Migration strategy: incremental steps, no big-bang rewrites
Follow this incremental pattern: (1) Switch createStore to configureStore, (2) Migrate one touched reducer to createSlice, (3) Convert touched connected components to hooks, (4) Repeat without introducing new legacy Redux code. Do not attempt to replace every reducer, every connected component, and every async flow in one branch before shipping.
Stop adding legacy Redux patterns once store is modernized
Once the store is modernized to configureStore and createSlice, new work should not introduce legacy Redux patterns like hand-written reducers, combineReducers with applyMiddleware, or manual fetch-state management. Maintain modern patterns in all new features.
configureStore automatically combines reducers, adds thunk middleware, and sets up Redux DevTools
The configureStore function sets up a well-configured Redux store with a single function call. It automatically passes slice reducers to combineReducers, automatically adds the redux-thunk middleware, adds dev-mode middleware to catch accidental mutations, automatically sets up Redux DevTools Extension integration, and composes the middleware and DevTools enhancers together and adds them to the store. At the same time, configureStore provides options to let users modify any of those default behaviors.