Notes about Redux

Redux

Redux is a JavaScript library that can be used with various JavaScript frameworks, including React, Angular, Vue, and Vanilla JS. It serves as a state management tool for handling cross-component or app-wide state.

In simpler terms, Redux functions as a centralized container for storing the state (data that, when modified, impacts the UI) of your JavaScript application. This state is then accessible across all your components.

Why Use Redux?

While React Context can handle cross-component or app-wide state (as discussed in React useContext), there are drawbacks to consider:

  • Complex Setup and Management: In complex applications, using Context can lead to deeply nested or overly complex provider components.
  • Performance: While React Context is suitable for low-frequency updates, such as user data or themes, it may not be optimal for high-frequency state changes in applications.

By opting for Redux, you gain a structured approach to managing your application’s state, particularly when dealing with complex or frequently changing data across components.

Installing Redux

Below command will install the Redux in your application.

npm i redux

How does Redux work?

The core concepts of Redux are Store, Actions, Reducers, and Subscriptions.

React Redux Diagram

React Redux Diagram

Let’s check the core concepts individually.

Store

Store is an immutable object which holds the entire state of your application. It is the single source for state and created by using createStore method from Redux.

// Create Redux store
const store = redux.createStore(counterReducer);

Actions

Actions are payloads of information that describes an events, user interactions, API calls, or form submissions. They are plain JavaScript objects typically comprising a type property indicating the action to perform and an optional payload property containing data to change the application’s state.

Action creators are functions responsible for creating and returning these action objects. When an action needs to be executed, the dispatch() method is used to send the action to the Redux store. This method triggers the reducer functions, which update the state based on the action type and payload, leading to a predictable and centralized state management approach.

// Actions
store.dispatch({ type: 'INCREMENT'});

Reducers

In Redux, reducers are pure functions that take the current state of an application and an action as arguments, and return a new state. They define how the application’s state changes in response to actions sent to the store.

How Reducers work

  • Initialization Process: When the application starts, the Redux store invokes the reducer function with an initial undefined state and an action of { type: ‘@@redux/INIT’ }. The reducer then returns the initial state to set up the store.

  • Handling Dispatched Actions: When an action is dispatched using the dispatch method, the Redux store calls the reducer function with the current state and the dispatched action as arguments.

  • Action Type Verification: Inside the reducer, the action type is checked to determine how to modify the current state. If the action type matches one of the defined cases in the reducer (like ‘INCREMENT’ or ‘DECREMENT’), the reducer updates the state accordingly. If no action type matches, the reducer returns the default state.

// Define initial state
const initialState = { count: 0 };

// Reducer function
const counterReducer = (state = initialState, action) => {
    switch(action.type){
        case 'INCREMENT':
            return {counter: state.count + 1};
        case 'DECREMENT':
            return {counter: state.count - 1};   
        default:
            return state;
    }
};

Subscriptions

Subscriptions in Redux serve as listener methods within the store, providing a mechanism for components to track changes in the store’s state. When a component subscribes to the Redux store, it becomes capable of receiving notifications whenever the store’s state undergoes a change, allowing the component to update its UI accordingly.

In the below you can see the component is subscribed to the store using the method subscribe and it can read the current state with the store method getState. Also subscibe will returns a function that unsubscribe the component from further state change notifications. It’s crucial to unsubscribe components when they are no longer needed, such as when they are unmounted, to prevent memory leaks and unnecessary updates.

const counterSubscriber = () => {
    const latestState = store.getState();
    console.log(latestState);
}

// Subscribe a component to the Redux store
const unsubscribe = store.subscribe(counterSubscriber);

//..
unsubscribe();

Full Example

Here’s the full example illustrating the above concepts:

const redux = require('redux');

// Define initial state and reducer function
const initialState = { count: 0 };

// Reducer
const counterReducer = (state = initialState, action) => {
    switch(action.type){
        case 'INCREMENT':
            return {counter: state.count + 1};
        case 'DECREMENT':
            return {counter: state.count - 1};   
        default:
            return state;
    }
};

// Create a Redux store using the reducer
const store = redux.createStore(counterReducer);

// Function will be called whenever the Redux store's state changes.
const counterSubscriber = () => {
    const latestState = store.getState();
    console.log(latestState);
}

// Subscribe a component to the Redux store
const unsubscribe = store.subscribe(counterSubscriber);

// Actions
store.dispatch({ type: 'INCREMENT'});
store.dispatch({ type: 'DECREMENT'});

// Unsubscribe the component when it's no longer needed
unsubscribe();

Summary

  • Store: Handles the applications state.
  • Actions: Plain JavaScript objects consisting a type property indicating the action to perform and an optional payload property containing data to change the application’s state.
  • Reducers: Pure funcitons that take the current state of an application and an action as arguments, and return a new state.
  • Subscriptions: Listener methods within the store, providing a mechanism for components to track changes in the store’s state.

By using Redux you can manage state in complex applications in a structured and predictable way. Its core components (store, actions, reducers, and subscriptions) work together to ensure that state management is centralized, predictable state changes, and debugging is straight forward. This makes Redux particularly beneficial for complex applications with frequent state changes and a need for clear state management practices.


Read More