Digging into Redux middlewares, and exploring Redux-Thunk.

Shubhnik Singh Mann
3 min readOct 29, 2017

--

If you have been into front-end development and if React happens to be your preferred choice then chances are high that you have used redux. If you are using redux then chances are that you might have used some middlewares, for example like redux-logger, thunk, sagas etc.

Prerequisites

To understand some code below you should have understanding of some Functional programming techniques like currying and composition.

How Middlewares work?

Basically a middleware acts on the actions, implements the desired functionality before the action reaches the reducer and ultimately updates the store. For example, redux-thunk delays the action being dispatched to reach reducer until the asynchronous task completes.

Left: Actions dispatches without middleware, Right: Actions being acted upon by middleware

Entry point for middlewares — applyMiddleware

Middlewares are introduced to the redux setup using the redux utility applyMiddleware . applyMiddleware accepts all the middlewares, composes them and allow the action to pass through it before reaching the reducer. Here’s how we apply middlewares using applyMidlleware :

import { applyMiddleware } from "redux";

const store = createStore(
reducers,
initialState,
applyMiddleware(
middleware1,
middleware1,
middleware3
)
);

In the gist I have tried to explain how the applyMiddleware works, the applyMiddleware function in the gist is same as that of the redux’s very own. If more than one middlewares are fed to applyMiddleware, then they are composed and the last middleware in the chain will receive the store’s original dispatch and the final output will be the new wrapped dispatch once all middlewares are iterated through. So action will be dispatched using the new dispatch method.

How redux middleware works and writing a redux middleware

A middleware in redux accepts store as the first parameter and returns a curried function. A simple redux middleware is as follows:

dummyMiddleware = store => next => action => {  
setTimeout(() => next(action), 5000)
}

It receives the store parameter which include the default dispatch , then returns a function which receives the wrapped dispatch if any other middleware is present to its right. Finally it returns a function which accepts the redux action and dispatches the action to the store after doing what it is meant for. In the above middleware we are just delaying the action by 5 seconds before its is dispatched to the store. Here is a little demonstration repo, where I integrated this 5 second middleware to the redux.

Special Case: Redux-thunk

If you have used redux-thunk then this section is for you.

https://github.com/gaearon/redux-thunk/blob/master/src/index.js

Yes! Redux-thunk is all these 11 lines of code, and the purpose is seemingly understandable. It just checks the type of the action and take the decision as follows:

  1. If the action is of the type function then it calls the function which is fed as the parameter and feeding it with dispatch , getState and extraArgument . Following is a little code snippet:
dispatch( actionFunction())actionFunction = () => ({dispatch, getState, extraArgument}) => {
// Here we have access to the wrapped dispatch created by the
// middleware, we can do the async task and then dispatch
// the action.
// Code ...
// Code ...
}

2. If the action is of the type object then it let complete the normal chain and introduce no effect to the default dispatch and the action is dispatched to the store as it would have had there been no middleware.

Conclusion

Diving into redux code helped me understand many new things. One should never hesitate diving into code because you got to learn new thing every time. So keep calm and dive into code 🤘 💻

--

--