Skip to content

Commit

Permalink
Remove middleware array option
Browse files Browse the repository at this point in the history
  • Loading branch information
EskiMojo14 authored and markerikson committed Oct 1, 2023
1 parent a98875c commit d248e7a
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 101 deletions.
16 changes: 11 additions & 5 deletions packages/toolkit/src/configureStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export interface ConfigureStoreOptions<
* @example `middleware: (gDM) => gDM().concat(logger, apiMiddleware, yourCustomMiddleware)`
* @see https://redux-toolkit.js.org/api/getDefaultMiddleware#intended-usage
*/
middleware?: ((getDefaultMiddleware: GetDefaultMiddleware<S>) => M) | M
middleware?: (getDefaultMiddleware: GetDefaultMiddleware<S>) => M

/**
* Whether to enable Redux DevTools integration. Defaults to `true`.
Expand Down Expand Up @@ -121,7 +121,7 @@ export function configureStore<

const {
reducer = undefined,
middleware = getDefaultMiddleware(),
middleware,
devTools = true,
preloadedState = undefined,
enhancers = undefined,
Expand All @@ -139,15 +139,21 @@ export function configureStore<
)
}

let finalMiddleware = middleware
if (typeof finalMiddleware === 'function') {
finalMiddleware = finalMiddleware(getDefaultMiddleware)
if (!IS_PRODUCTION && middleware && typeof middleware !== 'function') {
throw new Error('"middleware" field must be a callback')
}

let finalMiddleware: Tuple<Middlewares<S>>
if (typeof middleware === 'function') {
finalMiddleware = middleware(getDefaultMiddleware)

if (!IS_PRODUCTION && !Array.isArray(finalMiddleware)) {
throw new Error(
'when using a middleware builder function, an array of middleware must be returned'
)
}
} else {
finalMiddleware = getDefaultMiddleware()
}
if (
!IS_PRODUCTION &&
Expand Down
23 changes: 12 additions & 11 deletions packages/toolkit/src/tests/configureStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ describe('configureStore', async () => {
describe('given no middleware', () => {
it('calls createStore without any middleware', () => {
expect(
configureStore({ middleware: new Tuple(), reducer })
configureStore({ middleware: () => new Tuple(), reducer })
).toBeInstanceOf(Object)
expect(redux.applyMiddleware).toHaveBeenCalledWith()
expect(mockDevtoolsCompose).toHaveBeenCalled() // @remap-prod-remove-line-line
Expand All @@ -122,6 +122,15 @@ describe('configureStore', async () => {
})
})

describe('given an array of middleware', () => {
it('throws an error requiring a callback', () => {
// @ts-expect-error
expect(() => configureStore({ middleware: [], reducer })).toThrow(
'"middleware" field must be a callback'
)
})
})

describe('given undefined middleware', () => {
it('calls createStore with default middleware', () => {
expect(configureStore({ middleware: undefined, reducer })).toBeInstanceOf(
Expand Down Expand Up @@ -162,20 +171,12 @@ describe('configureStore', async () => {
})
})

describe('given custom middleware that contains non-functions', () => {
it('throws an error', () => {
expect(() =>
configureStore({ middleware: [true] as any, reducer })
).toThrow('each middleware provided to configureStore must be a function')
})
})

describe('given custom middleware', () => {
it('calls createStore with custom middleware and without default middleware', () => {
const thank: Redux.Middleware = (_store) => (next) => (action) =>
next(action)
expect(
configureStore({ middleware: new Tuple(thank), reducer })
configureStore({ middleware: () => new Tuple(thank), reducer })
).toBeInstanceOf(Object)
expect(redux.applyMiddleware).toHaveBeenCalledWith(thank)
expect(mockDevtoolsCompose).toHaveBeenCalled() // @remap-prod-remove-line-line
Expand Down Expand Up @@ -330,7 +331,7 @@ describe('configureStore', async () => {
it("doesn't warn when middleware enhancer is excluded if no middlewares provided", () => {
const store = configureStore({
reducer,
middleware: new Tuple(),
middleware: () => new Tuple(),
enhancers: () => new Tuple(dummyEnhancer),
})

Expand Down
17 changes: 8 additions & 9 deletions packages/toolkit/src/tests/configureStore.typetest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,19 @@ const _anyMiddleware: any = () => () => () => {}

configureStore({
reducer: () => 0,
middleware: new Tuple(middleware),
middleware: () => new Tuple(middleware),
})

configureStore({
reducer: () => 0,
// @ts-expect-error
middleware: [middleware],
middleware: () => [middleware],
})

configureStore({
reducer: () => 0,
// @ts-expect-error
middleware: new Tuple('not middleware'),
middleware: () => new Tuple('not middleware'),
})
}

Expand Down Expand Up @@ -520,7 +520,7 @@ const _anyMiddleware: any = () => () => () => {}
{
const store = configureStore({
reducer: reducerA,
middleware: new Tuple(),
middleware: () => new Tuple(),
})
// @ts-expect-error
store.dispatch(thunkA())
Expand All @@ -533,7 +533,7 @@ const _anyMiddleware: any = () => () => () => {}
{
const store = configureStore({
reducer: reducerA,
middleware: new Tuple(thunk as ThunkMiddleware<StateA>),
middleware: () => new Tuple(thunk as ThunkMiddleware<StateA>),
})
store.dispatch(thunkA())
// @ts-expect-error
Expand All @@ -545,9 +545,8 @@ const _anyMiddleware: any = () => () => () => {}
{
const store = configureStore({
reducer: reducerA,
middleware: new Tuple(
0 as unknown as Middleware<(a: StateA) => boolean, StateA>
),
middleware: () =>
new Tuple(0 as unknown as Middleware<(a: StateA) => boolean, StateA>),
})
const result: boolean = store.dispatch(5)
// @ts-expect-error
Expand All @@ -566,7 +565,7 @@ const _anyMiddleware: any = () => () => () => {}
>
const store = configureStore({
reducer: reducerA,
middleware,
middleware: () => middleware,
})

const result: 'A' = store.dispatch('a')
Expand Down
63 changes: 33 additions & 30 deletions packages/toolkit/src/tests/getDefaultMiddleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,18 @@ describe('getDefaultMiddleware', () => {
it('allows passing options to immutableCheck', () => {
let immutableCheckWasCalled = false

const middleware = getDefaultMiddleware({
thunk: false,
immutableCheck: {
isImmutable: () => {
immutableCheckWasCalled = true
return true
const middleware = () =>
getDefaultMiddleware({
thunk: false,
immutableCheck: {
isImmutable: () => {
immutableCheckWasCalled = true
return true
},
},
},
serializableCheck: false,
actionCreatorCheck: false,
})
serializableCheck: false,
actionCreatorCheck: false,
})

const reducer = () => ({})

Expand All @@ -172,17 +173,18 @@ describe('getDefaultMiddleware', () => {
it('allows passing options to serializableCheck', () => {
let serializableCheckWasCalled = false

const middleware = getDefaultMiddleware({
thunk: false,
immutableCheck: false,
serializableCheck: {
isSerializable: () => {
serializableCheckWasCalled = true
return true
const middleware = () =>
getDefaultMiddleware({
thunk: false,
immutableCheck: false,
serializableCheck: {
isSerializable: () => {
serializableCheckWasCalled = true
return true
},
},
},
actionCreatorCheck: false,
})
actionCreatorCheck: false,
})

const reducer = () => ({})

Expand All @@ -200,17 +202,18 @@ describe('getDefaultMiddleware', () => {
it('allows passing options to actionCreatorCheck', () => {
let actionCreatorCheckWasCalled = false

const middleware = getDefaultMiddleware({
thunk: false,
immutableCheck: false,
serializableCheck: false,
actionCreatorCheck: {
isActionCreator: (action: unknown): action is Function => {
actionCreatorCheckWasCalled = true
return false
const middleware = () =>
getDefaultMiddleware({
thunk: false,
immutableCheck: false,
serializableCheck: false,
actionCreatorCheck: {
isActionCreator: (action: unknown): action is Function => {
actionCreatorCheckWasCalled = true
return false
},
},
},
})
})

const reducer = () => ({})

Expand Down

0 comments on commit d248e7a

Please sign in to comment.