Redux is an open-source JavaScript library for managing the state of an application. It is commonly used with React, but it can be used with any JavaScript framework or library. Redux provides a predictable state container, which means that the state of an application is managed in a single, centralized store. This makes it easier to manage and update the state of an application, especially in large and complex applications.
The main principles of Redux include:
Single Source of Truth: The state of the entire application is stored in a single JavaScript object, known as the "store." This makes it easy to manage and debug the state of the application.
State is Read-Only: The state in a Redux application cannot be directly modified. Instead, to make changes to the state, you dispatch actions. Actions are plain JavaScript objects that describe the type of change you want to make to the state.
Changes are Made with Pure Functions: To specify how the state changes in response to an action, you use pure functions called "reducers." Reducers take the current state and an action as arguments and return a new state. They should be predictable and not have side effects.
Unidirectional Data Flow: In a Redux application, data flows in a unidirectional manner. When an action is dispatched, it flows through the reducers to update the state in the store, and then the updated state is reflected in the UI.
Middleware: Redux allows the use of middleware to extend its capabilities. Middleware can be used for logging, asynchronous operations, and more.
React-Redux Flow:
Major Components and Flow of Redux without middleware:
Store/State:
Centralized state container.
Holds the entire state of the application.
Reducer:
Pure functions that specify state changes.
Combined into a root reducer.
Return new state based on dispatched actions.
Action:
Plain JavaScript objects.
Describes the type of change to be made to the state.
Triggered by components using action creators.
Dispatch:
Mechanism to send actions to the store.
Triggers the execution of reducers.
Connect (React-Redux):
Connects React components to the Redux store.
Maps state and actions to component props.
Facilitates interaction between React and Redux.
Provider (React-Redux):
Wraps the root component.
Passes the Redux store to all connected components.
In summary, Redux has a unidirectional data flow, where actions trigger state changes through reducers, and connected React components efficiently update and display the application's state.
Here is the CodeSandbox link showcasing a basic implementation of Redux for a todo app.
https://codesandbox.io/p/sandbox/redux-demo-y9f5kx
Why middleware is necessary in Redux?
In React applications, asynchronous operations like making API calls or handling side effects can be managed effectively using middleware. Middleware allows developers to intercept certain actions, perform asynchronous tasks, and then dispatch new actions with the results once the tasks are complete.
For instance, when I want to initiate an API call and subsequently dispatch an action based on the response like adding the API response as a payload. As standard Redux doesn't permit direct integration of an asynchronous API call followed by dispatching an action. Redux Thunk which allow async call and after that it manually dispatch action.
Action Creation:
Actions are created as plain JavaScript objects with a
type
property to describe the action.Thunk allows you to create action creators that return functions instead of plain action objects.
Thunk Action Creator:
Thunk action creators return functions that can perform asynchronous operations.
These functions receive
dispatch
as an argument, which is used to dispatch other actions.
Async Logic in Thunk:
Within the thunk function, you can perform asynchronous operations, such as API calls or other side effects.
Thunk allows you to delay the dispatch of an action or dispatch multiple actions based on the asynchronous result.
Dispatch Actions:
- Inside the thunk function, you can use
dispatch
to dispatch actions, including both synchronous and asynchronous actions.
- Inside the thunk function, you can use
Reducer:
Reducers handle the dispatched actions and update the state based on the action type.
Reducers should be pure functions that take the current state and an action, and return the new state.
Store:
The store holds the application state and allows access to it via
getState
.Middleware, such as Thunk, enhances the store's capabilities by intercepting actions before they reach the reducer.
Middleware Execution:
Thunk middleware intercepts actions before they reach the reducer.
If an action is a function (thunk), it is executed with
dispatch
andgetState
as arguments.This enables asynchronous behavior and conditional dispatching based on the result of asynchronous operations.
Async Completion:
Asynchronous operations complete, and subsequent actions are dispatched within the thunk function.
These subsequent actions can be used to update the state based on the results of the asynchronous operations.
Here is the CodeSandbox link that showcases the implementation of Redux with Thunk middleware for a shopping cart.
https://codesandbox.io/p/sandbox/redux-middleware-h78hkj