The applyMiddleware function

Learn about the applyMiddleware function.

One of the best-known store enhancers is applyMiddleware(). This is currently the only store enhancer provided by Redux. The redux code in the library is as follows:

export default function applyMiddleware(...middlewares) {
  return (createStore) => (reducer, preloadedState, enhancer) => {
    var store = createStore(reducer, preloadedState, enhancer)
    var dispatch = store.dispatch
    var chain = []

    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return { ...store, dispatch }
  }
}

At its core, applyMiddleware() changes the store’s default dispatch() method to pass the action through the chain of middleware provided by the user:

var store = createStore(reducer, preloadedState, enhancer)
var dispatch = store.dispatch
var chain = []

var middlewareAPI = {
  getState: store.getState,
  dispatch: (action) => dispatch(action)
}

First, a store is created, and the core getState() and dispatch() methods are wrapped in middlewareAPI. This is the object our middleware receives as the first parameter.

chain = middlewares.map(middleware => middleware(middlewareAPI))

The array of middleware is transformed into calling middleware() with middlewareAPI as its argument. This essentially passes the middlewareAPI through all the middleware that the user has specified.

The last stage is to use the compose() function to decorate the middleware one after another:

dispatch = compose(...chain)(store.dispatch)

This line causes each middleware to decorate the chain of previous ones in a fashion similar to this:

middlewareA(middlewareB(middlewareC(store.dispatch)));

The original store.dispatch() passes as a parameter to the first wrapper in the chain.

Get hands-on with 1200+ tech skills courses.