You can include custom middleware functions to the dispatch method of your store.

The dispatch function is responsible for sending actions to one or more reducer functions for state changes. The composed specialized functions around the original dispatch method creates the new middleware capable dispatch method.

Source code for applyMiddleware(from Redux 1.0.1)

export default function applyMiddleware(...middlewares) {
  return (next) =>
    (reducer, initialState) => {
      var store = next(reducer, initialState);
      var dispatch = store.dispatch;
      var chain = [];

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

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

      return {
        ...store,
        dispatch
      }
    }
}
`</pre>

Composing Functions

Functional programming is very literal and very mathematical. In the case of composing functions with math you can express two or more functions like this:

<pre>`given:

f(x) = x^2 + 3x + 1
g(x) = 2x

then:
(f · g)(x) = f(g(x)) = f(2x) = 4x^2 + 6x + 1
`</pre>

It is no coincidence that you can compose two or more functions in a similar fashion. Here is a very simple example of a function that composes two functions to return a new specialized function:

<pre>`var greet = function(x) { return `Hello, ${x}`}
var emote = function(x) { return `${x} :)`}

var compose = function(f,g){
  return function(x){
    return f(g(x))
  }
}
`</pre>

This was just to illustrate the basic concept. We will look at a more generic way to solve that issue by examining the Redux Code.

### Currying

Another powerful functional programming concepts is the idea of currying or partially applying argument values to a function. By currying we can create a new specialized function that has partial information supplied to it. Here is the canonical example of currying where we have an add function that curries the first operand parameter to create a specialized add function

<pre>`var curriedAdd = function(a){
  return function(b){
    return a + b;
  }
}

var addTen = curriedAdd(10);
addTen(10); // 20
`</pre>

By currying and composing your functions you can create powerful new functions that create a pipeline for data processing.

### Redux Dispatch Function

A Store in Redux have a dispatch method which is only concerned with the main execution task you are interested in. You dispatch actions to your reducer functions to update state of the application. Redux reducers function takes a state and action parameter and return a new resultant state.

<pre>`reducer:: state -&gt; action -&gt; state
`</pre>

You might dispatch an action that simply sends a message to remove an item in a list which could look like this:

<pre>`{type: types.DELETE_ITEM, id: 10}
`</pre>

The store will dispatch this action object to all of it's reducer functions which could affect state. However the reducer functions are only concerned with executing logic around this deletion. They typically don't care who did it, how long it took, or logging the before and after effects of the state changes. This is where middleware can help us to address non-core concerns.

### Redux middleware

Redux middleware is designed by creating functions that can be composed together before the main dispatch method is invoked.

Let's creating a very simple logger middleware function that can echo the state of your application before and after running your main dispatch function. Redux middleware functions have this signiture:

<pre>`middleware:: next -&gt; action -&gt; retVal
`</pre>

It might look something like this:

<pre>`export default function createLogger({getState}){
  return (next) =&gt;
    (action) =&gt; {
      const console = window.console;
      const prevState = getState();
      const returnValue = next(action);
      const nextState = getState();
      const actionType = String(action.type);
      const message = `action ${actionType}`;

      console.log(`%c prev state`, `color: #9e9e9e`, prevState);
      console.log(`%c action`, `color: #03A9F4`, action);
      console.log(`%c next state`, `color:#4CAF50`, nextState)
    };
}
`</pre>

Notice that createLogger accepts the getState method which is injected by applyMiddleware.js and used inside closure to read the current state. This will return a new function with the `next` parameter which is used to compose the next chained middleware function or the main dispatch function.

This function returns a curried function that accepts the action object which can be read or modified before sending it to the next middleware function in the chain. Finally the main dispatch function is invoked with the action object.
  • First it captures the previous state

  • The action is dispatched to the next middleware function

  • All downstream middleware functions in the chain are invoked

  • The reducer functions in the store are called with the action payload

  • The logger middleware the gets the resulting next state

    Dissecting applyMiddleware.js

    `export default function applyMiddleware(...middlewares){
      return (next) =>
        (reducer, initialState) => {
          var store = next(reducer, initialState);
          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
          };
        };
    }
    `

    The applyMiddleware function probably could have been named a little better, such as applyMiddlewareToStore.

    The applyMiddleware function returns a function that takes a mysterious next argument:

    `return (next) => (reducer, initialState) => {...}
    `

    The next argument will be a function that is used to create a store. By default you should look at the implementation for createStore. The final returned function will be like createStore and replace the dispatch function with it’s associated middlewares.

    Next we assign the store implementation to the function responsible for creating the new store. Then we create a variable to the store’s original dispatch function. Finally we setup an array to hold the middleware chain we will be creating.

    `var store = next(reducer, initialState)
    var dispatch = store.dispatch
    var chain = [];
    `

    This next bit of code injects the getState function and the original dispatch function from the store into each middleware function which you can optionally use in your middleware(the applyMiddleware function pass getState and dispatch to middlewares in it).

    The resultant middleware is stored in the chain array

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

    Now we create our replacement dispatch function with the information about hte middleware chain:

    `dispatch = compose(...chain, store.dispatch);
    `

    The magic to composing our middleware chain lies in this utility function supplied by Redux. Here is the implementation

    `export default function compose(...funcs){
      return funcs.reduceRight((compsed,f) => f(composed))
    }
    `

    The composing function will literally express your functions as a composition injecting each middleware as an argument to the next middleware in the chain. Order is important here when assembling your middleware function. Finally, the original store dispatch method is composed. This new looks like:

    `middlewareI(middlewareJ(middlewareK(store.dispatch)))(action)
    `

    The final thing to do is return the new store object with the overriden function:

    `return {
      ...store,
      dispatch
    }
    `

    Let’s add our logger middleware we started above into a custom store with the enhanced dispatch function.

    `import { createStore, applyMiddlware } from 'redux'
    import loggerMiddleware from 'logger'
    import rootReducer from './reducers'
    
    const createStoreWithMiddleware = applyMiddleware(loggerMiddleware)(createStore)
    
    export default function configureStore(initialState){
      return createStoreWithMiddleware(rootReducer, initialState);
    }
    
    const store = configureStore()
    `

    Asynchronous Middleware

    Once you get comfortable with the basics of Redux middleware you will likely want to work with asynchronous actions that involve some sort of asynchronous execution. In particular look at ‘redux-thunk’ for more details. Let’s say you have an action creator that has some async functionality to get stock quote information:

    `function fetchQuote(symbol){
      requestQuote(symbol);
      return fetch('......')
             .then(req => req.json())
             .then(json => showCurrentQuote(symbol, json));
    }
    `

    There is no obvious way here to dispatch an action that would be returned from the fetch which is Promise based. Plus we do not have a handle to the dispatch function. Therefore we can use the redux-thunk middleware to defer execution of these operations. By wrapping the execution in a function you can delay this execution:

    `function fetchQuote(symbol){
      return dispatch => {
        dispatch(requestQuote(symbol));
        return fetch('......').then(req=>req.json).then(json => dispatch(showCurrentQuote(symbol,json))
      }
    }
    `

    Remember that the applyMiddleware function will inject the dispatch and the getStat function as parameters int o the redux-thunk middleware. Now you can dispatch the resultant action objects to your store which conatains reducers. Here is the middleware function for redux-thunk that does this for you.

    `export default function thunkMiddleware({dispatch,getState}){
      return (next) =>
                action => {
                  typeof action === 'function'? action(dispatch, getState):next(action)
                }
    }
    
    

If the action is a function it will be called with the dispatch and getState function..