0
# Store Configuration
1
2
Redux Toolkit's store configuration provides a simplified API over Redux's `createStore()` with sensible defaults, automatic middleware setup, and enhanced developer experience features.
3
4
## Capabilities
5
6
### Configure Store
7
8
Creates a Redux store with good defaults including Redux Thunk, Redux DevTools integration, and development-time invariant checking middleware.
9
10
```typescript { .api }
11
/**
12
* A friendly abstraction over Redux's createStore() with good defaults
13
* @param options - Configuration options for the store
14
* @returns Enhanced Redux store with thunk support and additional methods
15
*/
16
function configureStore<
17
S = any,
18
A extends Action = AnyAction,
19
M extends Middlewares<S> = Middlewares<S>,
20
E extends Enhancers = Enhancers
21
>(options: ConfigureStoreOptions<S, A, M, E>): EnhancedStore<S, A, E>;
22
23
interface ConfigureStoreOptions<S, A extends Action, M extends Middlewares<S>, E extends Enhancers, P = S> {
24
/** Root reducer or reducer map object */
25
reducer: Reducer<S, A> | ReducersMapObject<S, A>;
26
/** Callback to customize middleware array (receives getDefaultMiddleware) */
27
middleware?: ((getDefaultMiddleware: GetDefaultMiddleware<S>) => M) | M;
28
/** Enable Redux DevTools (default: true in development) */
29
devTools?: boolean | DevToolsOptions;
30
/** Initial state value */
31
preloadedState?: P;
32
/** Callback to customize store enhancers */
33
enhancers?: ((getDefaultEnhancers: GetDefaultEnhancers<S>) => E) | E;
34
}
35
36
interface EnhancedStore<S = any, A extends Action = AnyAction, E = any> extends Store<S, A> {
37
/** Dispatch function with thunk support */
38
dispatch: Dispatch<A> & ThunkDispatch<S, any, A>;
39
}
40
```
41
42
**Usage Examples:**
43
44
```typescript
45
import { configureStore } from '@reduxjs/toolkit';
46
import counterSlice from './features/counter/counterSlice';
47
import todosSlice from './features/todos/todosSlice';
48
49
// Basic store setup
50
const store = configureStore({
51
reducer: {
52
counter: counterSlice.reducer,
53
todos: todosSlice.reducer
54
}
55
});
56
57
// Custom middleware configuration
58
const store = configureStore({
59
reducer: rootReducer,
60
middleware: (getDefaultMiddleware) =>
61
getDefaultMiddleware({
62
serializableCheck: {
63
ignoredActions: ['persist/PERSIST']
64
}
65
}).concat(logger),
66
devTools: process.env.NODE_ENV !== 'production'
67
});
68
69
// With preloaded state
70
const store = configureStore({
71
reducer: rootReducer,
72
preloadedState: {
73
counter: { value: 5 },
74
todos: []
75
}
76
});
77
78
export type RootState = ReturnType<typeof store.getState>;
79
export type AppDispatch = typeof store.dispatch;
80
export default store;
81
```
82
83
### Default Middleware
84
85
Get the default middleware array that includes Redux Thunk and development-time checking middleware.
86
87
```typescript { .api }
88
/**
89
* Returns the default middleware array used by configureStore
90
* @param options - Options to customize the default middleware
91
* @returns Array of middleware functions
92
*/
93
interface GetDefaultMiddleware<S> {
94
<O extends MiddlewareOptions<S>>(options?: O): Tuple<DefaultMiddlewareArray<S, O>>;
95
}
96
97
interface MiddlewareOptions<S> {
98
/** Enable thunk middleware (default: true) */
99
thunk?: boolean | ThunkOptions<S>;
100
/** Enable immutable state invariant middleware (default: true in development) */
101
immutableCheck?: boolean | ImmutableStateInvariantMiddlewareOptions;
102
/** Enable serializable state invariant middleware (default: true in development) */
103
serializableCheck?: boolean | SerializableStateInvariantMiddlewareOptions;
104
/** Enable action creator invariant middleware (default: true in development) */
105
actionCreatorCheck?: boolean | ActionCreatorInvariantMiddlewareOptions;
106
}
107
108
type DefaultMiddlewareArray<S, O extends MiddlewareOptions<S>> = [
109
ThunkMiddleware<S>,
110
...ConditionalMiddleware<O['immutableCheck'], ImmutableStateInvariantMiddleware<S>>,
111
...ConditionalMiddleware<O['serializableCheck'], SerializableStateInvariantMiddleware>,
112
...ConditionalMiddleware<O['actionCreatorCheck'], ActionCreatorInvariantMiddleware>
113
];
114
```
115
116
**Usage Examples:**
117
118
```typescript
119
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
120
import logger from 'redux-logger';
121
122
// Add custom middleware to defaults
123
const store = configureStore({
124
reducer: rootReducer,
125
middleware: (getDefaultMiddleware) =>
126
getDefaultMiddleware()
127
.prepend(
128
// Correctly typed middleware can be added before
129
rateLimitMiddleware({ requests: 5, window: 1000 })
130
)
131
.concat(
132
// And after the defaults
133
logger
134
)
135
});
136
137
// Customize default middleware options
138
const store = configureStore({
139
reducer: rootReducer,
140
middleware: (getDefaultMiddleware) =>
141
getDefaultMiddleware({
142
thunk: {
143
extraArgument: { api, analytics }
144
},
145
serializableCheck: {
146
ignoredActions: ['persist/PERSIST', 'persist/REHYDRATE']
147
}
148
})
149
});
150
151
// Disable development middleware in production
152
const store = configureStore({
153
reducer: rootReducer,
154
middleware: (getDefaultMiddleware) =>
155
getDefaultMiddleware({
156
immutableCheck: process.env.NODE_ENV !== 'production',
157
serializableCheck: process.env.NODE_ENV !== 'production'
158
})
159
});
160
```
161
162
### Store Enhancers
163
164
Configure store enhancers for additional functionality like persistence or analytics.
165
166
```typescript { .api }
167
/**
168
* Get default store enhancers (auto-batching by default)
169
* @param options - Options to customize enhancers
170
* @returns Array of store enhancers
171
*/
172
interface GetDefaultEnhancers<S> {
173
<O extends EnhancerOptions>(options?: O): Tuple<DefaultEnhancerArray<S, O>>;
174
}
175
176
interface EnhancerOptions {
177
/** Enable auto-batching enhancer (default: true) */
178
autoBatch?: boolean | AutoBatchOptions;
179
}
180
181
type DefaultEnhancerArray<S, O extends EnhancerOptions> = [
182
...ConditionalEnhancer<O['autoBatch'], AutoBatchEnhancer>
183
];
184
185
/** Store enhancer for automatic action batching */
186
function autoBatchEnhancer(options?: AutoBatchOptions): StoreEnhancer;
187
188
interface AutoBatchOptions {
189
/** Custom batch type checker */
190
type?: 'tick' | 'timer' | 'callback' | ((action: Action) => boolean);
191
}
192
```
193
194
**Usage Examples:**
195
196
```typescript
197
import { configureStore, autoBatchEnhancer } from '@reduxjs/toolkit';
198
import { persistStore, persistReducer } from 'redux-persist';
199
200
// Add persistence enhancer
201
const persistConfig = {
202
key: 'root',
203
storage,
204
};
205
206
const persistedReducer = persistReducer(persistConfig, rootReducer);
207
208
const store = configureStore({
209
reducer: persistedReducer,
210
enhancers: (getDefaultEnhancers) =>
211
getDefaultEnhancers().concat(
212
// Add your custom enhancers here
213
)
214
});
215
216
// Custom auto-batching configuration
217
const store = configureStore({
218
reducer: rootReducer,
219
enhancers: (getDefaultEnhancers) =>
220
getDefaultEnhancers({
221
autoBatch: { type: 'tick' }
222
})
223
});
224
```
225
226
### Development Middleware
227
228
Redux Toolkit includes several development-time middleware for catching common mistakes.
229
230
```typescript { .api }
231
/**
232
* Middleware that detects mutations to state
233
* @param options - Configuration options
234
* @returns Middleware function
235
*/
236
function createImmutableStateInvariantMiddleware<S = any>(
237
options?: ImmutableStateInvariantMiddlewareOptions
238
): Middleware<{}, S>;
239
240
interface ImmutableStateInvariantMiddlewareOptions {
241
/** Enable the middleware */
242
isImmutable?: (value: any) => boolean;
243
/** Paths to ignore when checking for mutations */
244
ignoredPaths?: string[];
245
/** Function to determine if checking should be ignored */
246
warnAfter?: number;
247
}
248
249
/**
250
* Middleware that detects non-serializable values in state and actions
251
* @param options - Configuration options
252
* @returns Middleware function
253
*/
254
function createSerializableStateInvariantMiddleware(
255
options?: SerializableStateInvariantMiddlewareOptions
256
): Middleware<{}, any>;
257
258
interface SerializableStateInvariantMiddlewareOptions {
259
/** Actions to ignore when checking */
260
ignoredActions?: string[];
261
/** Action paths to ignore */
262
ignoredActionPaths?: string[];
263
/** State paths to ignore */
264
ignoredPaths?: string[];
265
/** Function to determine if value is serializable */
266
isSerializable?: (value: any) => boolean;
267
/** Function to get entries from value for checking */
268
getEntries?: (value: any) => [string, any][];
269
/** Execution time warning threshold */
270
warnAfter?: number;
271
}
272
273
/**
274
* Middleware that validates action creators are not called incorrectly
275
* @param options - Configuration options
276
* @returns Middleware function
277
*/
278
function createActionCreatorInvariantMiddleware(
279
options?: ActionCreatorInvariantMiddlewareOptions
280
): Middleware;
281
282
interface ActionCreatorInvariantMiddlewareOptions {
283
/** Enable the middleware */
284
isActionCreator?: (action: any) => boolean;
285
}
286
```
287
288
**Usage Examples:**
289
290
```typescript
291
import {
292
configureStore,
293
createImmutableStateInvariantMiddleware,
294
createSerializableStateInvariantMiddleware
295
} from '@reduxjs/toolkit';
296
297
const store = configureStore({
298
reducer: rootReducer,
299
middleware: (getDefaultMiddleware) =>
300
getDefaultMiddleware({
301
// Configure immutable check
302
immutableCheck: {
303
ignoredPaths: ['items.dates'],
304
warnAfter: 128
305
},
306
// Configure serializable check
307
serializableCheck: {
308
ignoredActions: ['persist/PERSIST', 'persist/REHYDRATE'],
309
ignoredPaths: ['items.map'],
310
warnAfter: 128
311
}
312
})
313
});
314
```
315
316
## Store Types
317
318
### Enhanced Store Interface
319
320
```typescript { .api }
321
/**
322
* Extended Redux store with additional typing for thunk dispatch
323
*/
324
interface EnhancedStore<S = any, A extends Action = AnyAction, E = any> extends Store<S, A> {
325
dispatch: Dispatch<A> & ThunkDispatch<S, any, A>;
326
}
327
328
/**
329
* Configuration options for configureStore
330
*/
331
interface ConfigureStoreOptions<S, A extends Action, M extends Middlewares<S>, E extends Enhancers, P = S> {
332
reducer: Reducer<S, A> | ReducersMapObject<S, A>;
333
middleware?: ((getDefaultMiddleware: GetDefaultMiddleware<S>) => M) | M;
334
devTools?: boolean | DevToolsOptions;
335
preloadedState?: P;
336
enhancers?: ((getDefaultEnhancers: GetDefaultEnhancers<S>) => E) | E;
337
}
338
339
/**
340
* Redux DevTools configuration options
341
*/
342
interface DevToolsOptions {
343
/** Custom action name mapping */
344
actionCreators?: ActionCreatorMapObject;
345
/** Maximum number of actions to keep */
346
maxAge?: number;
347
/** Actions to skip in DevTools */
348
actionSanitizer?: (action: Action, id: number) => Action;
349
/** State sanitizer for DevTools */
350
stateSanitizer?: <S>(state: S, index: number) => S;
351
/** Trace option */
352
trace?: boolean;
353
/** Trace limit */
354
traceLimit?: number;
355
}
356
```
357
358
## Best Practices
359
360
### Store Organization
361
362
```typescript
363
// store/index.ts - Main store configuration
364
import { configureStore } from '@reduxjs/toolkit';
365
import { rootReducer } from './rootReducer';
366
367
export const store = configureStore({
368
reducer: rootReducer,
369
middleware: (getDefaultMiddleware) =>
370
getDefaultMiddleware({
371
serializableCheck: {
372
ignoredActions: ['persist/PERSIST', 'persist/REHYDRATE']
373
}
374
})
375
});
376
377
export type RootState = ReturnType<typeof store.getState>;
378
export type AppDispatch = typeof store.dispatch;
379
380
// store/rootReducer.ts - Combined reducers
381
import { combineReducers } from '@reduxjs/toolkit';
382
import counterSlice from '../features/counter/counterSlice';
383
import todosSlice from '../features/todos/todosSlice';
384
385
export const rootReducer = combineReducers({
386
counter: counterSlice.reducer,
387
todos: todosSlice.reducer
388
});
389
```
390
391
### Environment-Specific Configuration
392
393
```typescript
394
const store = configureStore({
395
reducer: rootReducer,
396
middleware: (getDefaultMiddleware) =>
397
getDefaultMiddleware({
398
// Disable dev middleware in production
399
immutableCheck: __DEV__,
400
serializableCheck: __DEV__,
401
thunk: {
402
extraArgument: { api, logger }
403
}
404
}),
405
devTools: __DEV__ && {
406
actionSanitizer: (action) => ({
407
...action,
408
// Remove sensitive data from DevTools
409
payload: action.type.includes('auth') ? '***' : action.payload
410
})
411
}
412
});
413
```