Redux Middleware — What is it? Why use it?

Dani Matton - Aria Web Solutions
3 min readMar 11, 2020

--

I have recently started working with Redux for state management in my React applications. Redux is often used alongside other libraries to enhance the state management process throughout the application, improving code reuse. Being new to Redux, I found myself using middleware in an application but knew only vaguely why, so I wanted to take a closer look at Redux middleware.

Middleware provides a way to interact with actions that have been dispatched to the store before they reach the store’s reducer. Some uses for middleware would be logging actions, reporting errors, making asynchronous requests, as well as dispatching new actions.

Below we see how Middleware is used by composing the functions, and passing that function to createStore. Side note: A composite function allows us to combine two functions in a way so the outputs of one function become the inputs of the other function.

import { applyMiddleware } from "redux";

const store = createStore(
reducers,
initialState,
applyMiddleware(
middlewareOne,
middlewareTwo
)
);

Middleware is essentially a piece of code that sits between your actions and your reducers. It takes your actions being applied and changes them before passing down to the reducer. So why use it? Say, for example, we are communicating with an external API. Middleware allows for side effects to be run without blocking state updates and this can be done in response to a specific action, or even every action that is dispatched (as mentioned above, logging).

In Redux, the series of events are as follows:

An action occurs => an action is dispatched => the reducer creates a new state based on the change imposed from the action => new state is passed via props into the React app

Now with a middleware, the series of events look like this:

An action occurs => an action is dispatched => middleware receives the action => the reducer creates the new state based on the change imposed from the action => new state is passed via props into the React app

applyMiddleware

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

Beginning at the top, we see an argument of middleware with the spread operator — applyMiddleware takes in any number of middleware functions, storing them in an array. It returns a function that takes a createStore function as its argument.

The next few lines include the store implementation being assigned to this createStore function, creating a variable for the stores dispatch function and then setting up an array to hold the middleware chain being created.

Next comes the getState function and original dispatch function being injected from the store into each middleware function, to then be stored within the chain array. Following that, we replace the dispatch function with the information coming from the middleware chain.

Finally the new store object including the overridden dispatch function is returned.

Understanding what applyMiddleware is really doing helps our overall understanding of middleware. Once we know what middleware is doing for us, we can look more specifically into what middleware libraries would best suit the project we are working on. Two common middleware libraries are Redux-Thunk and Redux-Saga.

Redux-Thunk

Redux-Thunk middleware allows you to write action creators that return a function rather than your typical action object. The thunk is used to delay the dispatch of an action until a line of asynchronous code is completed. Redux-Thunk has access to the full Redux application state and can dispatch actions. Generally speaking Redux-Thunk utilizes callback function.

Redux-Saga

Redux-Saga is a library built to make an applications side effects, such as fetching data, easier to handle and more efficiently executed. Redux-Saga also has access to the Redux state and can dispatch Redux actions as well, but unlike Thunk, a Redux-Saga thread can be started, paused and cancelled from the app using normal Redux actions.

There is a lot more to each of these libraries, so I’ll be following up with some of what I have learned in a blog post to follow!

--

--

Dani Matton - Aria Web Solutions

Freelance front-end developer | Microservices architect | Your go-to expert for building fast, scalable, and accessible web solutions.