• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import compose from './compose';
2import type { Middleware, MiddlewareAPI } from './types/middleware';
3import type { AnyAction } from './types/actions';
4import type { Dispatch, PreloadedState, StoreEnhancer, StoreEnhancerStoreCreator } from './types/store';
5import type { Reducer } from './types/reducers';
6
7/**
8 * Creates a store enhancer that applies middleware to the dispatch method
9 * of the Redux store. This is handy for a variety of tasks, such as expressing
10 * asynchronous actions in a concise manner, or logging every action payload.
11 *
12 * See `redux-thunk` package as an example of the Redux middleware.
13 *
14 * Because middleware is potentially asynchronous, this should be the first
15 * store enhancer in the composition chain.
16 *
17 * Note that each middleware will be given the `dispatch` and `getState` functions
18 * as named arguments.
19 *
20 * @param middlewares The middleware chain to be applied.
21 * @returns A store enhancer applying the middleware.
22 *
23 * @template Ext Dispatch signature added by a middleware.
24 * @template S The type of the state supported by a middleware.
25 */
26export default function applyMiddleware(): StoreEnhancer
27export default function applyMiddleware<Ext1, S>(
28  middleware1: Middleware<Ext1, S, any>
29): StoreEnhancer<{ dispatch: Ext1 }>
30export default function applyMiddleware<Ext1, Ext2, S>(
31  middleware1: Middleware<Ext1, S, any>,
32  middleware2: Middleware<Ext2, S, any>
33): StoreEnhancer<{ dispatch: Ext1 & Ext2 }>
34export default function applyMiddleware<Ext1, Ext2, Ext3, S>(
35  middleware1: Middleware<Ext1, S, any>,
36  middleware2: Middleware<Ext2, S, any>,
37  middleware3: Middleware<Ext3, S, any>
38): StoreEnhancer<{ dispatch: Ext1 & Ext2 & Ext3 }>
39export default function applyMiddleware<Ext1, Ext2, Ext3, Ext4, S>(
40  middleware1: Middleware<Ext1, S, any>,
41  middleware2: Middleware<Ext2, S, any>,
42  middleware3: Middleware<Ext3, S, any>,
43  middleware4: Middleware<Ext4, S, any>
44): StoreEnhancer<{ dispatch: Ext1 & Ext2 & Ext3 & Ext4 }>
45export default function applyMiddleware<Ext1, Ext2, Ext3, Ext4, Ext5, S>(
46  middleware1: Middleware<Ext1, S, any>,
47  middleware2: Middleware<Ext2, S, any>,
48  middleware3: Middleware<Ext3, S, any>,
49  middleware4: Middleware<Ext4, S, any>,
50  middleware5: Middleware<Ext5, S, any>
51): StoreEnhancer<{ dispatch: Ext1 & Ext2 & Ext3 & Ext4 & Ext5 }>
52export default function applyMiddleware<Ext, S = any>(
53  ...middlewares: Middleware<any, S, any>[]
54): StoreEnhancer<{ dispatch: Ext }>
55export default function applyMiddleware(
56  ...middlewares: Middleware[]
57): StoreEnhancer<any> {
58  return (createStore: StoreEnhancerStoreCreator) =>
59    <S, A extends AnyAction>(
60      reducer: Reducer<S, A>,
61      preloadedState?: PreloadedState<S>
62    ) => {
63      const store = createStore(reducer, preloadedState)
64      let dispatch: Dispatch = () => {
65        throw new Error(
66          'Dispatching while constructing your middleware is not allowed. ' +
67            'Other middleware would not be applied to this dispatch.'
68        )
69      }
70
71      const middlewareAPI: MiddlewareAPI = {
72        getState: store.getState,
73        dispatch: (action, ...args) => dispatch(action, ...args)
74      }
75      const chain = middlewares.map(middleware => middleware(middlewareAPI))
76      dispatch = compose<typeof dispatch>(...chain)(store.dispatch)
77
78      return {
79        ...store,
80        dispatch
81      }
82    }
83}
84