Let’s Consider we have a small application, with some components. Few of those components declare and use their own state. Now let’s suppose in some cases, a component might want to share its data with its immediate children(component). This can be done by declaring the state locally within the component itself and passing down that state as props to the children (also called prop drilling).
But what if your application grows in size and there comes a situation where you want to pass the data several steps down the component hierarchy? In this case, we will declare a state in the parent’s component and pass it down to the child component via prop drilling. This will become a costly operation.
Consider the following diagram:
In the above diagram, consider we need to share the same type of data between the Child 4 component and Child 5 component, to do so we will declare a state in the Child 1 component and then pass that state in the Child 4 component and Child 5 component as props. But what if we need to pass the same state to Child 4, Child 9, and Child 10? As done before we need to declare a state in the App component and do several multi-levels of prop drilling to pass the State from the App component to Child 4, Child 9, and Child 10.
But this will create a problem as the application grows in size App.js will have unnecessary state declarations, or any other parent component will have unnecessary state declarations that they won't be using at all. Also, another disadvantage of this is the re-rendering of components which makes the application slow, and unresponsive. Rendering is caused by any change in the state or prop. In the above example, any component which has a state declared in it and acts as a passage from parent to child will get re-rendered unnecessarily when its state or prop changes.
The solution to this problem is state management that is we have to manage our state in such a way that it doesn't make our application slower and the components aren't re-rendered unnecessarily. And this is where Redux comes into the picture. Redux has the facility for state management and is efficient to use it. Here we can create a global state and put it in a store. If any component needs that state they can fetch it from there. Now Let us see discuss more Redux,
What is Redux?
Redux is nothing but a state management library for JavaScript apps. It is mostly used with React simultaneously, but can be used with other frameworks like Angular, Vue, etc. It helps manage the state of the application in a centralized manner, meaning the entire state of the application is stored in one JavaScript object known as “store”. Redux is also predictable in nature, meaning we will know how the state will change at a given time and what “action” is performed on it.
There are 3 main pillars or 3 main components of Redux:
Store:
The global state of an application is stored in an object tree within a single store – Redux docs
It acts a container where the global state of the application is stored and maintained. It is the center stage of any application which uses Redux. There can only be one single store in the Redux application. In Redux, if you want to modify the state you must dispatch an action to the store. The store has 3 critical methods:
- getState()- It returns the current state of the store.
- dispatch(action) - dispatches an action. It is the only way to modify the application state.
- subscribe ()-which registers listeners, allowing code to trigger every time a change takes place.
Action:
The only way to change the state is to emit an action, an object describing what happened - Redux docs
Actions are nothing but pure objects used to store user events. For example, Adding an item to a cart. They contain payloads of data that are the only way you can send data from your application to your Redux store. The data can be from user interactions like mouse clicks, API calls, or even form submissions.
• Actions must have a property ‘type’ to indicate the type of action to be carried out.
• It also contains the ‘payload’ property which contains the information or data used to change the state.
• If you want to execute any action, you will have to dispatch that action via the ‘dispatch’ method, which then sends the data to the store.
Reducer:
Reducers are pure functions that handle actions and update the state. They take the current state and an action as input and return a new state object without modifying the original state. Reducers are responsible for defining how the state should change in response to different actions. If it is a simple application you can create only one Reducer but as the application grows in size you may need to create multiple reducers and combine them with the help of the combineReducer() function.
Let us now Understand what is the flow of Redux in a pictorial way,
Pic Reference: https://dev.to/ashikacronj/react-redux-a-complete-guide-to-beginners-2a45
The flow of Redux can be summarized in the following steps:
- The application dispatches an action: The application can dispatch an action in response to a user interaction, a network request, or any other event.
- The Redux store receives the action: When an action is dispatched, the store receives the action and then it passes to the reducer.
- The reducer updates the store: The reducer updates the store with the new state, which represents the updated state of the application. So now the reducer contains the current state of the application.
- The store notifies the UI: After the store has been updated, it notifies the UI that a change has occurred. This allows the UI to re-render with the new state. The UI can read the current state of the application from the store at any time. This allows the UI to always display the most up-to-date information.
Let’s Understand Redux flow with a small Example,
Let’s say you are planning to take a vacation somewhere, so the first thing you will do is book a train.
Following will be the process,
Now Let’s see this example in terms of the Redux Analogy,
Pros and Cons of Redux:
Pros:
- Centralized State Management: Redux has a “single source of truth” for the entire application state called the store, thus it becomes easy for other components to access that state.
- Predictable state management: As Redux follows a strict unidirectional flow it becomes easy to understand why the data changes and how it changes. As Redux is predictable, it becomes easier for developers to track everything that is going on in the app such as actions and state changes.
- Performance Optimizations: Whenever a component’s state is updated React renders all the child components in that component tree. If the child component is not using that data the re-renders are wasted. As Redux manages the state centrally these re-renders won’t happen thus improving the performance.
- Time Travel Debugging: Redux maintains a history of actions that have been applied to the application state, allowing developers to easily undo or redo actions and debug the application in the past and present.
Cons:
- Encapsulation: As Redux doesn’t allow encapsulating data, any component can read the component from the store allowing security issues to be raised and if the application grows larger there will be more security concerns.
- Increased Complexity and Learning Curve: As Redux follows a certain structure it becomes difficult for developers who are beginners to setup the architecture of Redux as it needs a lot of boilerplate code to get started even for application which is smaller or medium-level. Thus, it has a steep learning curve which takes time for developers to master it. Redux also adds an extra layer of complexity to an application which can be overwhelming who are new to it.
- Excessive Memory usage: As the state is immutable thus when the state is being updated, the reducer has to return a new state every time. This leads to excessive memory usage in the long run of the application. Therefore, when the store gets bigger the memory usage gets higher.
Conclusion:
Redux is a powerful JavaScript library for managing the state of an application. It provides a centralized store for storing the application state, which makes it easier to manage and maintain that state. Redux follows a predictable and strict set of rules for updating the state, which helps in debugging and testing. We can track how the state changes and which action has triggered the change. It works well with large applications but it has its fair share of disadvantages such as, as the application gets larger it consumes more memory. It also adds complexity to an application, has a steep learning curve, requires a lot of boilerplate code, and may have a performance impact. While Redux has its benefits that does not mean that you should always use Redux in your app. It is necessary to consider its pros and cons.
In this blog, I have discussed the core concepts of Redux, but to see the implementation of it, follow This blog.
Thanks for Reading! 😊
Top comments (1)
Very detailed and easy to grasp.