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