Custom Redux Middlewares with Example

vishal.chandna   |  14th November, 2018

Redux has now become an integral part of the web app development, especially when developed with React. It offers so much flexibility and scalability that no other library as of now. With good coding practices, it is now very feasible to use redux even for small projects and for incremental projects it really leads the way. 

Redux is not just only about the store, actions and reducers, it is much more powerful, robust and scalable when middlewares are used. Conventionally, the middlewares come under the advanced redux but I think middlewares are also a very important part of the redux architecture. 

What is a Redux Middleware?

A redux middleware is nothing more than a function which is invoked on every action and we can do almost anything e.g Data manipulations, popups, confirmations, API response validation and more, before pushing the updates to the reducers followed by the state change. 

Advantages

  1. Helps in writing very reusable code.
  2. Writing unit tests becomes like heaven.
  3. A product becomes easily scalable.
  4. It makes the process completely automated.
  5. Tons of reducers are available in form of node packages e.g redux-saga, redux-thunk, redux-beacon and so on.
  6. A dev can write its own middleware.

Disadvantages

  1. Harder to grasp in the beginning.

How to write your own middleware?
Writing middlewares is as simple as writing simple functions and all you need to do is wrap the middlewares in your redux store using applyMiddleware method. 

What are we going to make?

We are going to make an API middleware which will process our API requests and send the API response (success/error) and other data (isLoading / isLoaded). With this we won’t have to worry about writing the same code again and again, like retrieving the response data or setting/resetting the loading. Also, one of the biggest advantage is we can dispatch multiple actions inside our middleware when needed.

Let’s Get Started

  1. Let’s first setup our create-react-app with Redux. You guys can follow the following guide to setup the redux in your react application. https://medium.com/backticks-tildes/setting-up-a-redux-project-with-create-react-app-e363ab2329b8
  2. A redux middleware is a simple function which is a nested hierarchy of functions returning itself to its parent 
    const middleware = store => next => action => {
      // Code to be executed
    }

      OR 

    Const middleware = function(store) {
      return function(next) {
        return function(action) {
          // Code to be executed
        }
      }
    }

    Where store =  Redux store, next = Dispatch function, action = Action fired by the user

  3. Our middleware must come into play when there is an API request action needs to be performed and else for other actions it shouldn’t do anything.

  4. We are going to add our custom attributes e.g type replaced with types, introducing API attribute.

  5. Our action would look something like this 

    function requestData(data) {
      return {
        types: [DATA_REQUEST, DATA_SUCCESS, DATA_ERROR ],
        api: axios.get(“https://jsonplaceholder.typicode.com/posts”)
      }
    }

    You can see here, we have modified the type to types in order to dispatch multiple actions. E.g Firing loading actions to set/reset isLoading before and after the API request.

  6. Let’s start writing our middleware and add some validations to make it only work for API requests

    const apiMiddleware = store => next => action => {
    
      // If action is a function
      if (typeof action === 'function') {
        return action(dispatch, getState);
      }
    
      const { api, types, ...rest } = action;
    
      // If api is not there, it will filter out our non-api requests
      If (!api) {
        return next(action);
      }
    }

    We need to include this newly created middleware inside the store, which will make it work for all the actions

  7. We have now filtered the API request, it’s time to add the actual action which is going to request our data.The final code looks something like this - https://github.com/vishalchandna1/react-example/blob/redux-middleware/src/redux/middlewares/api.js

  8. We need to define a reducer to handle the state changes. There are a few cases that are required for our current scenario. POSTS_REQUEST - Fired when the posts are requested, POSTS_REQUEST_SUCCESS - Fired once the posts are fetched successfully POSTS_REQUEST_FAILURE - Fired if there is some api failures. The final code will look something like this - https://github.com/vishalchandna1/react-example/blob/redux-middleware/src/redux/modules/api.js

You can use the redux dev extension to know about the changes and actions fired. In this way you will be able to check state diffs on each action.

Code Repository - https://github.com/vishalchandna1/react-example/tree/redux-middleware 

Summary

We have implemented an API middleware function which is fired on all the action and filters out the API actions. A number of actions are fired e.g setting/resetting the loading before and after the API is requested and the final response is received. The code might confuse you a bit but try to understand the big picture here. With middlewares, we wouldn’t have to worry about handling the same stuff repeatedly.