Skip to content

Commit a0d51ef

Browse files
authored
Merge pull request #3461 from reduxjs/enhancer-callback-2
2 parents a2f3c9a + 3696b49 commit a0d51ef

File tree

3 files changed

+38
-26
lines changed

3 files changed

+38
-26
lines changed

packages/toolkit/src/configureStore.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export interface ConfigureStoreOptions<
8282
* and should return a Tuple of enhancers (such as `getDefaultEnhancers().concat(offline)`).
8383
* If you only need to add middleware, you can use the `middleware` parameter instead.
8484
*/
85-
enhancers?: ((getDefaultEnhancers: GetDefaultEnhancers<M>) => E) | E
85+
enhancers?: (getDefaultEnhancers: GetDefaultEnhancers<M>) => E
8686
}
8787

8888
export type Middlewares<S> = ReadonlyArray<Middleware<{}, S>>
@@ -172,13 +172,18 @@ export function configureStore<
172172
const middlewareEnhancer = applyMiddleware(...finalMiddleware)
173173

174174
const getDefaultEnhancers = buildGetDefaultEnhancers<M>(middlewareEnhancer)
175+
176+
if (!IS_PRODUCTION && enhancers && typeof enhancers !== 'function') {
177+
throw new Error('"enhancers" field must be a callback')
178+
}
179+
175180
let storeEnhancers =
176-
(typeof enhancers === 'function'
181+
typeof enhancers === 'function'
177182
? enhancers(getDefaultEnhancers)
178-
: enhancers) ?? getDefaultEnhancers()
183+
: getDefaultEnhancers()
179184

180185
if (!IS_PRODUCTION && !Array.isArray(storeEnhancers)) {
181-
throw new Error('enhancers must be an array')
186+
throw new Error('"enhancers" callback must return an array')
182187
}
183188
if (
184189
!IS_PRODUCTION &&
@@ -194,7 +199,7 @@ export function configureStore<
194199
!storeEnhancers.includes(middlewareEnhancer)
195200
) {
196201
console.error(
197-
'middlewares were provided, but middleware enhancer was not included in final enhancers'
202+
'middlewares were provided, but middleware enhancer was not included in final enhancers - make sure to call `getDefaultEnhancers`'
198203
)
199204
}
200205

packages/toolkit/src/tests/configureStore.test.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -283,16 +283,28 @@ describe('configureStore', async () => {
283283
undefined,
284284
expect.any(Function)
285285
)
286+
287+
expect(dummyEnhancerCalled).toBe(true)
286288
})
287289

288-
it('accepts a callback for customizing enhancers', () => {
289-
const store = configureStore({
290-
reducer,
291-
enhancers: (getDefaultEnhancers) =>
292-
getDefaultEnhancers().concat(dummyEnhancer),
290+
describe('invalid arguments', () => {
291+
test('enhancers is not a callback', () => {
292+
expect(() => configureStore({ reducer, enhancers: [] as any })).toThrow(
293+
'"enhancers" field must be a callback'
294+
)
293295
})
294296

295-
expect(dummyEnhancerCalled).toBe(true)
297+
test('callback fails to return array', () => {
298+
expect(() =>
299+
configureStore({ reducer, enhancers: (() => {}) as any })
300+
).toThrow('"enhancers" callback must return an array')
301+
})
302+
303+
test('array contains non-function', () => {
304+
expect(() =>
305+
configureStore({ reducer, enhancers: (() => ['']) as any })
306+
).toThrow('each enhancer provided to configureStore must be a function')
307+
})
296308
})
297309

298310
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
@@ -306,20 +318,20 @@ describe('configureStore', async () => {
306318
it('warns if middleware enhancer is excluded from final array when middlewares are provided', () => {
307319
const store = configureStore({
308320
reducer,
309-
enhancers: new Tuple(dummyEnhancer),
321+
enhancers: () => new Tuple(dummyEnhancer),
310322
})
311323

312324
expect(dummyEnhancerCalled).toBe(true)
313325

314326
expect(consoleSpy).toHaveBeenCalledWith(
315-
'middlewares were provided, but middleware enhancer was not included in final enhancers'
327+
'middlewares were provided, but middleware enhancer was not included in final enhancers - make sure to call `getDefaultEnhancers`'
316328
)
317329
})
318330
it("doesn't warn when middleware enhancer is excluded if no middlewares provided", () => {
319331
const store = configureStore({
320332
reducer,
321333
middleware: new Tuple(),
322-
enhancers: new Tuple(dummyEnhancer),
334+
enhancers: () => new Tuple(dummyEnhancer),
323335
})
324336

325337
expect(dummyEnhancerCalled).toBe(true)

packages/toolkit/src/tests/configureStore.typetest.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,13 @@ const _anyMiddleware: any = () => () => () => {}
147147

148148
const store = configureStore({
149149
reducer: () => 0,
150-
enhancers: new Tuple(enhancer),
150+
enhancers: () => new Tuple(enhancer),
151151
})
152152

153153
const store2 = configureStore({
154154
reducer: () => 0,
155155
// @ts-expect-error
156-
enhancers: [enhancer],
156+
enhancers: () => [enhancer],
157157
})
158158

159159
expectType<Dispatch & ThunkDispatch<number, undefined, AnyAction>>(
@@ -164,7 +164,7 @@ const _anyMiddleware: any = () => () => () => {}
164164
configureStore({
165165
reducer: () => 0,
166166
// @ts-expect-error
167-
enhancers: new Tuple('not a store enhancer'),
167+
enhancers: () => new Tuple('not a store enhancer'),
168168
})
169169

170170
{
@@ -192,10 +192,8 @@ const _anyMiddleware: any = () => () => () => {}
192192

193193
const store = configureStore({
194194
reducer: () => 0,
195-
enhancers: new Tuple(
196-
somePropertyStoreEnhancer,
197-
anotherPropertyStoreEnhancer
198-
),
195+
enhancers: () =>
196+
new Tuple(somePropertyStoreEnhancer, anotherPropertyStoreEnhancer),
199197
})
200198

201199
expectType<Dispatch>(store.dispatch)
@@ -254,14 +252,11 @@ const _anyMiddleware: any = () => () => () => {}
254252

255253
const store = configureStore({
256254
reducer: () => ({ aProperty: 0 }),
257-
enhancers: new Tuple(
258-
someStateExtendingEnhancer,
259-
anotherStateExtendingEnhancer
260-
),
255+
enhancers: () =>
256+
new Tuple(someStateExtendingEnhancer, anotherStateExtendingEnhancer),
261257
})
262258

263259
const state = store.getState()
264-
265260
expectType<number>(state.aProperty)
266261
expectType<string>(state.someProperty)
267262
expectType<number>(state.anotherProperty)

0 commit comments

Comments
 (0)