Redux to the Rescue

State management systems in React using Redux from Scratch.

Shubham Deodhar
DataX Journal
9 min readAug 25, 2020

--

Hello there, this blog is going to be about state management systems in React using Redux. Before we kick-off, let’s get a quick feel for the topic by going through some simple definitions.

So what is React and States in React?

React is an open-source JavaScript library that is used for building user interfaces specifically for single-page applications. It’s used for handling the view layer for web and mobile apps.

So how does it help to handle the view layer ?? The answer is simple. It uses a data-layer called states to control the View-layer of your web application. These states essentially describe the content of the interface. So, whenever the state changes the interface automatically updates to reflect the change. In short, we declaratively update the interface by updating the underlying state.

To display the data via state management, whenever and where ever it is required is a very crucial task when we are developing an application using react. It’s clear without saying that bigger the app, larger the data set which results in increased complexity of the state management system.

So should we avoid using React JS library while building large scale applications?

The answer is ‘No’. We can use React to build large scale apps. Let’s take the Instagram App as an example to better understand this concept.

Yes, your Instagram app uses a huge number of components (probably in thousands) and they all are built using React! Instagram has to manage a huge data set spread all over these components. So how do they do that?

The answer is Redux

Redux is an open-source javascript library used for application state management. It was released on 2nd June 2015. Since then, Redux got popular very quickly because of its simplicity, small size (only 2 KB), and great documentation.

So how does it work ??

In simple words, It combines all sources of data into single a store, creating a single source of truth, i.e single source for all kinds of data. So in this manner Redux improves the predictability of data outcome, makes data flow unidirectional, and provides strict code structure, making the code easier to maintain.

So, How does Redux Achieve this Strict Structure and Single Source of truth?

Redux state flow structure with React-based UI

Redux divides our complete state management system into three co-dependent parts named 1. Action, 2. Reducer, 3. Single source of truth -Store.

1. Actions

Actions are nothing but the result of the user’s interaction with the UI. According to Redux.js.org — Actions are payloads of information that send data from your application to your store. They are the only source of information for the store.

In short, when any action gets executed, it sends a specific payload of information to the store. So its completely into our hands that how we define our action which is basically in a form of the function to obtain the desired payload.

2. Reducer

Reducer is a function which determines the changes to the state depending on what type of action is getting triggered. To keep our data organized we can create any number of reducer functions as we want. In the end, we can combine all reducers in a single reducer with a simple function provided by Redux itself called ‘combineReducers’. In this manner, we achieve two things, one is we keep the state’s data flow organized and second we keep our code cleaner.

3. Store

As its name suggests, the store stores all the data that should flow through the React states. If any component in your React app demands any data it will come from the store, thus making it the single source of truth.

So, using the above three parts of Redux, the unidirectional data flow goes like this -

  1. The user interacts with the UI of the app, setting the action in motion with a data set as payload.
  2. The action gets recognized by the Reducer function and asks the store to make the required changes to the state.
  3. The store makes the changes to the state by using the payload which was provided by the action and forwarded by Reducer function.
  4. When the process of changing the state gets over, the UI gets updated accordingly, providing the appropriate change to the user which he/she desired.

Now let’s dive into the coding part

Github link https://github.com/ShubhamDeodhar/rn-meals

Let’s examine the code for the small restaurant menu app. To keep it simple we will be using a dummy-data instead of connecting it to any backend service.

The dummy data will include multiple objects with some key-value pairs such as id, categoryId, title, affordability, complexity, imageUrl, duration, ingredients, steps, isGlutenFree, isVegan, isLactoseFree, and isVegetarian.

So, enough with this side work. Let’s discuss Redux.

So let’s begin with installing the required packages.

Now we have the dummy-data and required packages. So, let’s get started.

In our app, we have two main actions that will directly affect the data that we are passing to our components.

  1. Marking any dish as favorite.
  2. Setting filters to the dishes.

Let’s define these actions and pass the required payload as we discussed earlier.

In the above code, we created two action types named TOGGLE_FAVOURITE and SET_FILTERS. These two actions are associated with the Views (React components ) through toggleFavourite() and setFilters() functions respectively. These two functions will respond to particular events caused by the user and set the payload so that reducer can work on it.

So now we will use our Action types and their payloads to make desired changes in our state globally.

As this blog aims to explain the Redux concept, I am not going to explain javascript ES6 methods and conditional logic.

Here we imported the two actions which we created in action/meals.js folder so that we can access them and there Payload. We also imported our dummy-data, to fill our state.

One of the advantages of the Redux is being able to set a state globally. That means it can be accessed and changed from any component. We did the same thing in the above code. We created a constant named initialState which has three entities (meals which stores every meal, filteredMeals which stores only whose meals which pass our filters and favouriteMeals which we will populate when the user marks a particular dish as his favorite). As its name suggests, this will be the initial state whenever your app restarts.

Now we start changing our state according to the action passed to the reducer by using its payload. The mealsReducer function takes two arguments first one is the initialState which we created and another one is the action. Now we use Switch conditional structure to create separate cases for different actions-types. Here we have two actions that can cause the change to the state.

In switch-case TOGGLE_FAVOURITE, we will check if the particular dish is in the favouriteMeals array or not. If it is not there, we will concate it in our array, else we will splice it. Later you will see that we will associate this action to a Star icon to mark a dish favorite or unmark it.

Till now we have our actions and a reducer that acts on it. Now we need to save this state somewhere, somewhere we can access it from anywhere and anytime. So its time to create a single source of truth that is our store! It is essential to create the store in the file which is the first file to get executed by our development server so that each component can access it. So let’s create a store in app.js

Here we are using three inbuilt Redux components.

We used combineReducers to combine all reducer functions. Then we pass that all-inclusive reducer to the createStore method. If you check the code for reducer, you will notice that the reducer function returns the state. So our store gets populated with all the state entities from different reducers.

After that, we wrap all the components inside of the <Provider> component and pass our store as the store property making our store available globally.

Now we have complete Redux architecture ready. The only thing left is to connect it to the components where our users perform actions and we present data to them.

To do this, the old method was to create mapStateToProps and mapDispatchToProps functions and connecting the component via connect() method provided by the react-redux package. But as we all know, React 16.8.0 allows us to use Hooks API. Thus our react-redux package allows us to use useSelector() and useDispatch() hooks to complete our task more easily.

Let’s examine the codes from files Screens/favouriteScreens.js and Screens/mealDetailsScreen.js

In the above code, we directly accessed our Redux store state using a single useSelector() hook. So if you want to access the state data from any component you can do it with a single line of code.

Now we know how to access the store, now let’s see how we can change the store state.

In the above code, we imported useSelector() and useDispatch() hooks. We also imported toggleFavourite action because using this action we can pass the id of the particular meal to the reducer to mark it as favorite or remove it from favorite depending upon the current state.

So to perform our desired task we passed our toggleFavourite() action using useDispatch() inside our toggleFav function. Then we associated the toggleFav function to our star icon in our react-navigation so that users can interact with it and mark any dish as their favorite.

If the above code seems confusing to you then just look it to the react-navigation-stack documentation. It will clear your doubts.

But Redux will give you one advantage that it will keep the state unchanged throughout all render cycles. Of course, the state will return to its initial state as we don’t have any backend support. If you want to save it permanently, then its time to show your backend skills.

I hope this blog will encourage you to dive deep into the world of React, learn more interesting libraries and packages such as Redux and react-redux. I will keep publishing more interesting blogs related to MERN stack and associated technology, so be sure to look out for those!

Thanks a lot for reading.

Adios!

--

--

Shubham Deodhar
DataX Journal

MERN stack developer||React-native developer||wannabe Data Analyst||