Introduction to Redux: Building Scalable Frontend Projects

August 12, 2020

Introduction

This summer, I got the opportunity to intern at Narus as a Frontend Developer. It has been a wonderful experience so far, filled with loads of new learnings and takeaways.

During my internship period, I worked on the frontend development of MARTINI, a web app that turns investment agreements into structured data. I learnt various concepts including Hooks, TypeScript, data visualisation libraries like d3 and Nivo, and testing frameworks like Jest. But one of the most important things that I learnt was the concept of state management with Redux, which I want to talk about today.

What is Redux?

Redux is one of the most commonly used tools to build scalable frontend projects. In the documentation, Redux is described as a “predictable state container for JavaScript apps”. In simple terms, it is a tool that developers use for state management.

But before we dive into Redux, let’s first talk about state.

In React, state is an object that holds component information across renders. State is managed within the component. It starts with a default value when a component mounts and then undergoes changes, depending on the functionality that it implements.

State is used everywhere in an application, starting from the most basic tasks like implementing a checkbox or toggling a switch. As the application grows larger, the number of stateful components increases, with more complex values and nested variables. State management becomes difficult and could get out of hand. It then becomes necessary to have clear separations between different layers of the application.

For smaller applications, one way to get around this is to maintain state in a parent component, which then gets passed on to its children. This solution has limits once the project grows — as it would make the code harder to maintain when more states get added. Ideally, to preserve modularity, stateful logic should be abstracted away from the UI. Hence there comes a need for a more consistent way to keep track of state changes.

This is exactly where Redux comes in. With the help of its middleware, Redux gives each frontend component only those state values that it actually needs.

Where did we use Redux?

One of the places where we used Redux was for our search filters. Since we had a number of components, and each with multiple states across the component tree, Redux was an ideal choice.

Breaking down Redux

There are four fundamental building blocks of Redux: action, reducers, middleware, and most importantly, the Redux store. Let’s look at each of these individually.

The Store

The Redux store is responsible for storing all the state variables. It also provides a few helper functions to access the application state and dispatch actions. The Redux library offers a function createStore, which can be used to create the store. It takes a reducer as the first argument. We can also pass an initial state to createStore.

Reducers

Reducers are the most important concept in Redux. They are regular JavaScript functions that are responsible for producing the state of the application. They take in two arguments — the initial state and an action, and use them to produce the next state.

It’s important to keep in mind that Redux states are immutable, which means that the reducer cannot mutate the state in-place. It returns a copy of the state, leaving the original untouched.

So how does a reducer generate the next state?

In Redux, the only way to change the state is by going via the store. Reducers can connect with the store by dispatching an action.

Actions

An action is the only way through which application data (from API calls, form submissions etc.) can be sent to the store.

It is an object with two properties — type and payload. Type is a mandatory property that indicates how the state should change. The payload is an optional property containing data that gets merged into the existing state.

An action can be created using an action creator — which is a simple JavaScript function that returns an object with properties type and payload.

The above snippet is an example of an action creator that we used for our search filters. It describes two functionalities — adding a new filter and removing an existing one.

When an action is dispatched, it is sent by the store to the reducer. The reducer then examines the action, and depending on its type and payload, produces the next state.

Let’s now look at the reducer that will handle the two operations:

We pass in the current state (a Filters object, in this case) along with an action. The reducer checks the action’s type, reads the payload and produces a new state object.

That’s about it! A simple example that shows how the store, the actions and the reducer work in unison. This example illustrates how Redux can make state management much more organized, especially in large applications.

How can Redux be used?

Redux is platform agnostic and hence can be used with any library. Although most commonly associated with React, it can also be used with other libraries like Vue and Angular, or also as a stand-alone library without any frontend framework.

There are binding libraries to use Redux with any framework, and for React, it is react-redux.

React-Redux is the official Redux UI binding library for React. It contains a higher-order component Provider and methods like connect, which are used to connect a React component to the Redux store. You can find more information on this in the documentation.

Wrapping up

Redux is gaining popularity by the day, and is being used by many renowned companies like Instagram, Stack and Robinhood. It has over 140M downloads in 2020 alone, overtaking its counterparts like MobX and GraphQL.

Throughout this internship, there were many such concepts that I gained proficiency in. The work culture was extremely nurturing and supportive, which further encouraged me to research, experiment and look beyond the codebase.

Overall this internship was a wonderful experience, with loads of good memories and new learnings, and is something that I will always cherish!

Gayathri Venkatesh

A Computer Science student at IIIT Bangalore. Loves building new things and bringing ideas to life. Areas of interest include ML, AI and web development.