CodeParva Blogs

Developing Custom React-Redux Framework — Reducing Developer’s Effort

24 Feb, 2021

If you are new to redux and state management, you might be excited to use it. How simple and straightforward it is. One state across your application, working all of your components. But, if you have worked a bit with redux and state-management you know how complex it can become as your application grows.

This is something almost every developer team faces and something that we have also faced. Some either go uphill against it or develop custom frameworks to do the hard and redundant work. We at CodeParva, opted to develop our own custom framework on top of redux to facilitate easy and efficient state management easing the life of developers.

In this article we would be discussing what state and state-management is, and how Redux — a JS state container library, helps in efficient state management. Let’s roll!

What is state & state-management?

In modern day JS applications, state is nothing but data stored in JSON format. State management facilitates components (parts of application) to communicate with each other using state as the common ground. A data structure is created to represent the state, to which components read from and write to.

Most libraries, such as React, Angular, etc. are built with the capabilities for components to internally manage their state without any need for an external library or tool. It does well for smaller applications with a few components, but as the application grows bigger, managing state that is shared across large number of components becomes a chore and if not properly managed could harm the performance of your application.

In situations where we need to share the state between parent and child we would store the state in the parent component and share it with the child via props. Now imagine, what happens when a state has to be shared between components that are far apart in the component tree. It would become necessary to pass the state from one element to another before it gets to where it is required.

Basically the state needs to be stored at the right component that is common to both the components and then it is passed down to them.This makes the state difficult to maintain and less predictable. It also means passing data to components that do not need it.

It is clear that the state management gets messy as the app grows. This is why we need state management tools like Redux, MobX, Apollo etc; that makes it easier to maintain these states.

In this article, we would be looking into the details of Redux.

Redux:

Redux is a predictable state container for JavaScript applications. It serves as a centralized store for state that needs to be used across your entire application, while ensuring that the state can only be updated in a predictable fashion.

Redux is most commonly used as a state management tool with React, but, you can use it with any other JavaScript framework or library. It’s lightweight at 2KB (including dependencies), so you don’t have to worry about it making your application’s asset size bigger.


image of the redux logo

How Redux works

Redux comprises of three building blocks: store, action and reducer.

Store holds the application data & functions. The store is actually an object. It contains a few extra things other than your application’s state as well (like functions and other objects).

Although, theoretically, it is possible to create multiple stores, this is against the pattern that Redux follows.

The state in Redux is in the form of a JavaScript Object and is often referred to as the “state tree”. You can put whatever values you want to store in it and you can nest them as much as you need.

Actions are plain JavaScript objects that describe WHAT happened, but don’t describe HOW the app state changes. They are the cause for state changes

Actions are events which are triggered by any user action or as a side effect of any other event. They are the only way you can send data from your application to your Redux store.

Reducers are pure functions that define HOW the app state changes. In other words, they are used to recalculate the new application state or, at least a part of it.

Whenever there’ a cause (we dispatch an action to our store, the action gets passed to the reducer) the state changes. Taking the current app state and the action as inputs the reducer function derives the new app state. In other words, the reducer will calculate the new state of our app based on the action (and its type) we dispatched.

In a real-world application, your reducers most probably will get very complex. To deal with reducer complexity, we chunk them down in multiple, simpler reducers and later, we combine them with a Redux helper function called combineReducers.

Redux Data Flow



image showing the redux flow

src: www.tutorialspoint.com

  • The event triggered by the VIEW dispatches an action.
  • Redux passes down the dispatched action to the reducer
  • Reducer uses the action to change the data for store
  • Store saves the new state returned by reducer
  • All the VIEW which subscribed to the store will get the updated state

Why use Redux

There are many reasons to use the redux in your application. Some of the benefits of using redux are:

  • Redux makes the state predictable: As we discussed earlier redux is a pure function, the state is always predictable. For the same state and action the same result is always produced.
  • Debugging is easy in Redux: Redux has great DevTools that allow you to time-travel actions, persist actions on page refresh, etc. For medium- and large-scale apps, debugging takes more time then actually developing features. Redux DevTools makes it easy to take advantage of all Redux has to offer.
  • Performance Benefits: React is generally fast, but by default any updates to a component will cause React to re-render all of the components inside that part of the component tree. This does require work, and if the data for a given component hasn’t changed, then re-rendering is likely some wasted effort because the requested UI output would be the same. If performance is a concern, the best way to improve performance is to skip unnecessary re-renders, so that components only re-render when their data has actually changed. React Redux implements many performance optimizations internally, so that your own component only re-renders when it actually needs to.
  • Community Support: As the official binding library for React and Redux, React Redux has a large community of users. This makes it easier to ask for help, learn about best practices, use libraries that build on top of React Redux, and reuse your knowledge across different applications.

React and Redux

Redux is a standalone JS library. We can create and use a Redux store even if you don’t have a user interface setup. This also means that we can use Redux with any UI framework (or even without any UI framework), and use it on both client and server. We can write Redux apps with React, Vue, Angular, Ember, jQuery, or vanilla JavaScript.

That said, Redux was specifically designed to work well with React. React lets you describe your UI as a function of your state, and Redux contains state and updates it in response to actions. Because of that, we’ll use React references and cover the basics of how to use React with Redux.

Let’s take a look at how Redux interacts with a UI layer in general.

Basic Redux and UI Integration: Using Redux with any UI layer requires a few consistent steps:

  1. Create a Redux store
  2. Subscribe to updates
  3. Inside the subscription callback: (i) Get the current store state (ii) Extract the data needed by this piece of UI (iii) Update the UI with the data
  4. If necessary, render the UI with initial state
  5. Respond to UI inputs by dispatching Redux actions

Some common issues

  • Code Redundancy: It takes a little bit of learning effort to master the redux concepts. The integration to components looks straightforward but as your app grows we have lots of components to deal with and for each component we will have to subscribe to the store and handle their data.
  • Async Logic and Data Fetching
  • Redux works synchronously and updates the store in the same manner. To make it work asynchronously we need to use third party libraries such as redux-thunk.

To overcome most of these challenges, we have created our own config driven framework on top of Redux. We created an HOC which is already wrapped in the connect method and has its mapStateToProps method in place. If there is a need for a component to access the redux store, we wrap it into this HOC and provide configs (such as the store keys it wants to listen to) and the component gets subscription for the store changes.

We have further customized this HOC to centralize the network calls. We can pass the network call config and the framework would take care of the network calls, handle the data, saves it in the store if required and send the data to the component that is listening to that store key. Each store key has its own status (Loading, Loaded, Error etc.) to indicate what is happening with the store key which helps us in making decisions such as there shouldn’t be any network call for the store keys which are in loading state.

Final Words:

Overall, redux is a very powerful and predictable state container library. It plays well with React and others JS frameworks/libraries. State being stored in a single object tree is easy to debug and log. 

Though it is what it is, redux may not suit every use case, and a little customization is always good. At CodeParva, we have developed our own customized wrapper for redux that has made the developer’s life easy and less redundant. Even if he/she is not fully aware of the core concepts of redux he/she can still manage to interact with store with much hustle.

In our future articles, we would be discussing the redux framework in more detail and we would explain how we used a custom wrapper to ease our life.

Visit CodeParva Technologies to know more about us. Linkedin | Instagram

Additional Links:

Author(s)

Aishwary Kumar

Editor(s)

Divyansh Sharma