State Management With Redux-Toolkit

What is a State?

React, a state can be seen as a piece of information that a component holds, which influences how the component behaves and what it displays on the screen. It acts as a sort of memory for the component, storing values that can change over time.

React has a built-in hook called useState() for managing states. A state variable and its setter function are declared within the scope of the component using this hook. The current state value and a method to alter that value are the two items of the array that the useState() hook delivers. The component re-renders whenever the state is changed by using the setter function, reflecting the modified data on the page.

Official Link to the documentation for useState()

Here is a sample demonstration of useState() hook in React

import React,{useState} from "react"

const App=()=>{
    const [counter,setCounter]=useState(0)
    const handleIncrement=()=>{
        setCounter(count+1)
    }
    const handleDecrement=()=>{
        setCounter(counter-1)
    }
    return(
    <div>
        <span>{counter}</span>
        <button onClick={handleIncrement}>+</button>
        <button onClick={handleDecrement}>-</button>
    </div>
    )
}
export default App

In the above example, the variables counter and setCounter represent the state variable and the setter method for the state variable, On clicking the + button you increase the counter by 1 and on Clicking the - button you decrease the counter by 1, These actions trigger updates to the state, reflecting the changes in the counter value.

Although the idea of state is useful, managing it in complicated applications may be difficult. There may be several state variables present in each component that needs to be shared and provided to other components for them to render data. The management of the logic and debugging process may become challenging as a result. Redux is a solution that is used to deal with these kinds of issues.

Redux

Redux is a JavaScript library commonly used with the React framework to efficiently organize and manage application states. It facilitates the storage of states in a centralized store, enabling updates through appropriate actions and functions.

Actions in redux are the events that want to bring a change in a particular state present in the centralised redux store.The functions that update the state as a response to these actions are called Reducers.It is considered a good practice to have Action Creators in the application which dispatch specific actions to the reducers

Here is a sample demonstration of Redux

import {createStore} from "redux"

const counterReducer=(state=0,action)=>{
    switch(action.type){
        case "INCREMENT":
            return state+1
        case "DECREMENT":
            return state-1
        default:
            return 0
    }

} 

const store=createStore(counterReducer)

store.dispatch("INCREMENT")
console.log(store.getState())
store.dispatch("DECREMENT")
console.log(store.getState())

In the provided code sample, the createStore function is imported from the Redux library, which allows us to create a central store that holds all the states of the application. The store is responsible for managing the state and facilitating state updates.

A function named counterReducer is defined, which serves as a reducer function. Reducers specify how the state should change in response to different actions. The counterReducer function takes two parameters: state and action. The state parameter represents the current state, which defaults to 0 if no state is initially provided. The action parameter represents the action being dispatched.

Within the counterReducer function, a switch statement is used to check the action.type and perform different logic based on the action type. In this case, if the action.type is INCREMENT, the reducer returns the incremented value of the state by adding 1. If the action.type is DECREMENT, the reducer returns the decremented value of the state by subtracting 1. If the action.type does not match any of the defined cases, the reducer returns 0.

The store variable is created by calling the createStore function and passing the counterReducer as a parameter. This sets up the Redux store with the initial state and the ability to handle actions through the provided reducer function. To dispatch an action to the store, the store.dispatch method is used. The store.getState() function is used to retrieve the current state from the store. It returns the current value of the state

Redux Toolkit

When developing complex applications with Redux, the configuration process can become cumbersome. One particular challenge arises when incorporating multiple states into the Redux store, which necessitates the use of another Redux function called combineReducers(). Additionally, the need to bundle action creators in separate files for different reducers further contributes to project complexity.

As the application grows in size and complexity, managing numerous reducers and their associated actions becomes increasingly unwieldy. Each reducer typically has its own set of actions, making it necessary to organize and maintain these actions in separate files. This separation of concerns can lead to a more complicated project structure

Redux Toolkit is a powerful library that builds upon the solid foundations of Redux, offering effective solutions to address the challenges faced in complex applications.

It eases the configuration process of a store by providing us with a configureStore() function, saves developers some time by performing tasks such as including middleware in the store automatically. The createSlice() function of Redux-Toolkit streamlines the action creators and reducers in a single object, it eliminates the need to have action creators and reducers in a different file.

The main task of Redux-Toolkit is to encapsulate all the configuration and management tasks which helps the developer to focus on the main logic of the application

Here is a sample Demonstration of Redux-Toolkit

import {configureStore,createSlice} from "@reduxjs/toolkit"

const counterSlice=createSlice(
    {
        name:"counterReducer",
        initialState:0,
        reducers:
        {
            increment:(state,action)=>
                       {
                           return state+1
                       }
            decrement:(state,action)=>
                       {
                            return state-1
                       }

        }

    }
)
const {reducer,actions}=counterSlice

const store=configureStore({
    reducer:{
        counterReducer:reducer
    }
})

store.dispatch(actions.increment())
console.log(store.counterReducer)
store.dispatch(actions.decrement())
console.log(store.counterReducer)

We can use Redux-Toolkit like this, but the most common implementation is to have a separate file for the store named store.js, a separate directory called features which stores all the slices, and making use of React hooks like useDispatch() and useSelector().

You can find the documentation on Redux-Toolkit Here

Therefore a result of streamlining the state management procedure and boosting developer productivity, Redux Toolkit shows to be a useful addition to the React ecosystem. Developers may concentrate more on the core application logic by utilising Redux Toolkit's simplified configuration, robust utilities, and opinionated conventions rather than being bogged down by lengthy setup and boilerplate code.