Redux Middleware => Code Perspective

Middleware is the suggested way to extend Redux with custom functionality. The most common use case for middleware is to support asynchronous actions without much boilerplate code or a dependency on any library.

We will be concentrating more on the inner workings of applyMiddleware function

Before we dive into, we need to take a look at 2 topics: currying and composing of functions :

Currying of Functions

Currying is the way of constructing functions that allows you to

  1. pass all the arguments a function is expecting and get the result or
  2. pass a subset of those arguments and get back a function that’s waiting for the rest of the arguments.

The Major advantage of using currying is partial application. You don’t need to provide all the arguments during function call. You can progressively provide a subset of the arguments when they are available and get intermediate functions .


compose.js — Composing JS functions

The compose function is a functional programming utility that composes single argument functions from right to left (taken from the argument list of middlewares).

Example :

compose(f, g, h) is identical to doing (…args) => f(g(h(…args)))

Note : The rightmost function can take multiple arguments as it provides the signature for the resulting composite function

applyMiddleware.js

The only store enhancer that ships with Redux is applyMiddleware. It provides (returns) a store enhancer to wrap the dispatch function with the middleware functions. This means whenever an action is fired first it is sent to the middleware before the reducers (if not blocked by the middleware). We can also create custom actions which can be intercepted and converted into action objects by the middleware (eg Redux-thunk).

Signature — ({ getState, dispatch }) => next => action

Simplest Middleware

const middlew = store => next => action => next(action);

Just forwards the action to the next middleware.

Walkthrough of the code

  1. Each middleware is given the `dispatch` and `getState` functions as named arguments and array ‘chain’ holds the returned intermediate functions which are of the signature next => action. The intermediate function are given the ‘next’ middleware’s dispatch method and is expected to return a function of action calling next(action).
  2. The new dispatch function is composed from the chain array and the store’s dispatch is sent to the last (rightmost) function(in the chain) as the ‘next’ parameter.

middle1 ( middle2 ( next ))

3. If next(action) is not called then the action is not forwarded to the next middleware (and eventually the reducers) and propagation of the action through the middlewares is stopped.

Example : When redux-thunk detects that the action fired is a function (not an object), it does not send that action to the next middleware.(does not call next(action)) Instead it executes the function by passing dispatch, getState and extraArgument as parameters to it.


I have tried to make the article as concise as possible retaining all what is think is most important to understand about redux middleware. Reach out to me in case of any suggestions or comments via email at : anooprav7@gmail.com. Image was procured for free from unsplash.com