Redux Tool Kit (RTK)

Redux Tool Kit (RTK)

Introduction

Redux Toolkit is a package that simplifies and streamlines the usage of Redux, a popular state management library for JavaScript applications. Redux Toolkit provides a set of tools and abstractions that make it easier to write Redux code with fewer lines and less boilerplate. It encourages best practices and helps developers write more maintainable and efficient Redux code.

Some key features and concepts of Redux Toolkit include:

  1. Redux Store Configuration: Redux Toolkit provides a configureStore() function, which combines several Redux store setup steps into a single function call. It sets up the Redux store with sensible defaults and includes built-in middleware, such as Redux Thunk for async actions.

  2. Simplified Reducer Logic: Redux Toolkit introduces a createSlice() function that reduces the amount of boilerplate required to define reducers. It generates action creators and action types automatically based on the provided reducer function.

  3. Immutable Updates: Redux Toolkit uses an optimized version of the Immer library under the hood to handle immutable updates to the Redux store. With Immer, you can write "mutating" code that looks like regular JavaScript, but it creates a new immutable state behind the scenes.

  4. DevTools Configuration: Redux Toolkit automatically sets up integration with the Redux DevTools Extension, a browser extension that provides advanced debugging and time-traveling capabilities for Redux.

  5. Additional Utilities: Redux Toolkit includes additional utilities like createAsyncThunk() for handling asynchronous actions, createEntityAdapter() for managing normalized data, and createSelector() for efficient and memoized data selection.

Installing Redux

To install Redux in a React project, you can follow these steps:

  1. Create a new React project using create-react-app or navigate to your existing React project directory.

  2. Open your terminal or command prompt and navigate to the project directory.

  3. Run the following command to install Redux and its dependencies via npm (Node Package Manager):

     npm install redux react-redux
    

    Alternatively, if you're using Yarn, you can use the following command:

     yarn add redux react-redux
    

    This command will install Redux and React Redux and add them as dependencies in your project's package.json file.

Installing RTK

To install Redux Toolkit (RTK) in your JavaScript project, you need to follow these steps:

  1. Create a new JavaScript project or navigate to your existing project directory in your terminal.

  2. Run the following command to install Redux Toolkit via npm (Node Package Manager):

     npm install @reduxjs/toolkit
    

    Alternatively, if you're using Yarn, you can use the following command:

     yarn add @reduxjs/toolkit
    

    This command will install Redux Toolkit and add it as a dependency in your project's package.json file.

General Work Flow of State Management in RTK

Let us Consider an example to further understand the workflow

Suppose we want to change the state when an item is selected and we want to put that item in the cart is pressed

  1. We will first configure a store redux toolkit which will be imported from the redux toolkit.

  2. In that store we will create different slices, it is these slices in which the update will be performed

  3. On the click of the add button which will help us to add an item to the cart, we will dispatch an action

  4. After the action is dispatched it will call a reducer.A reducer is basically a function that will perform the adding operation to the cart

  5. Remember our cart is basically a slice and it is the slice that has the reducer

  6. How to create a slice

    To create a slice in Redux using Redux Toolkit, you can follow these steps:

    1. Import necessary Redux Toolkit functions and utilities:

       import { createSlice } from '@reduxjs/toolkit';
      
    2. Define the initial state for your slice:

       const initialState = {
         count: 0,
         isLoading: false,
         error: null,
       };
      
    3. Create the slice using the createSlice() function:

       const counterSlice = createSlice({
         name: 'counter',
         initialState,
         reducers: {
           increment: (state) => {
             state.count += 1;
           },
           decrement: (state) => {
             state.count -= 1;
           },
           setCount: (state, action) => {
             state.count = action.payload;
           },
           setLoading: (state, action) => {
             state.isLoading = action.payload;
           },
           setError: (state, action) => {
             state.error = action.payload;
           },
         },
       });
      

      In the example above, we created a slice named 'counter' with the initial state defined earlier. Inside the reducers object, we defined several action reducers. Each reducer function receives the current state as the first argument and the action as the second argument. The reducer functions directly modify the state because Redux Toolkit uses Immer under the hood, allowing you to write "mutating" code.

    4. Export the generated action creators and the reducer:

       export const { increment, decrement, setCount, setLoading, setError } = counterSlice.actions;
       export default counterSlice.reducer;
      

      By exporting the generated action creators (increment, decrement, etc.) and the reducer (counterSlice.reducer), you can easily use them in other parts of your application.

  7. Configuring Our Store

     import { configureStore } from '@reduxjs/toolkit';
     import rootReducer from './reducers';
    
     const store = configureStore({
       reducer: {
         name: {userSlice.reducer}
    
     },
       // ... Additional configuration options
     });
    
     export default store;
    
  8. Provider tag indicates which all components should have access to the global storage

  9. Dispatching the action

    In Redux, useDispatch() is a hook provided by React Redux that allows you to access the dispatch function from the Redux store. You can use it in your functional components to dispatch actions and trigger state updates. Here's an example of how to use useDispatch():

    1. Import the necessary dependencies:

       import { useDispatch } from 'react-redux';
       import { increment, decrement } from './actions'; // Import your action creators
      
    2. Inside your functional component, call useDispatch() to get the dispatch function:

       const dispatch = useDispatch();
      
    3. Use the dispatch function to dispatch actions when needed:

       dispatch(increment()); // Dispatch the increment action
       dispatch(decrement()); // Dispatch the decrement action
      

      In the example above, we dispatched actions created by the increment and decrement action creators. These action creators are functions that return action objects, which have a type property and optionally a payload property.

Here's a complete example demonstrating the usage of useDispatch():

    import React from 'react';
    import { useDispatch } from 'react-redux';
    import { increment, decrement } from './actions'; // Import your action creators

    function Counter() {
      const dispatch = useDispatch();

      const handleIncrement = () => {
        dispatch(increment()); // Dispatch the increment action
      };

      const handleDecrement = () => {
        dispatch(decrement()); // Dispatch the decrement action
      };

      return (
        <div>
          <button onClick={handleIncrement}>Increment</button>
          <button onClick={handleDecrement}>Decrement</button>
        </div>
      );
    }

    export default Counter;

In the example above, we imported the useDispatch hook from react-redux and the increment and decrement action creators from your custom actions file. Inside the Counter component, we used useDispatch() to get the dispatch function, and then defined event handlers (handleIncrement and handleDecrement) that dispatch the respective actions when the buttons are clicked.

Using useDispatch() allows you to access the dispatch function in your functional components and dispatch actions to update the Redux store state.

  1. How to access the values for this we use a USEselector

    In Redux, useSelector() is a hook provided by React Redux that allows you to extract and access specific values from the Redux store state. It allows you to subscribe to changes in the Redux store and retrieve the selected data in your functional components. Here's an example of how to use useSelector():

    1. Import the necessary dependencies:

       import { useSelector } from 'react-redux';
      
    2. Inside your functional component, call useSelector() to select and retrieve the desired state value:

       const count = useSelector(state => state.counter.count);
      

      In the example above, we're using an arrow function inside useSelector(). The function takes the complete Redux store state as an argument and returns the selected value, which in this case is state.counter.count. state.counter corresponds to the slice name, and count corresponds to the property within that slice.

    3. Use the selected value in your component:

       return (
         <div>
           <p>Count: {count}</p>
         </div>
       );
      

      In this example, we're rendering the selected count value within a paragraph tag.

Here's a complete example demonstrating the usage of useSelector():

    import React from 'react';
    import { useSelector } from 'react-redux';

    function CounterDisplay() {
      const count = useSelector(state => state.counter.count);

      return (
        <div>
          <p>Count: {count}</p>
        </div>
      );
    }

    export default CounterDisplay;

In the example above, we imported the useSelector hook from react-redux. Inside the CounterDisplay component, we used useSelector() to select the count value from the counter slice of the Redux store state. We then rendered the selected count value within a paragraph tag.

By using useSelector(), you can access specific values from the Redux store state and automatically update your component whenever those values change. This allows you to efficiently retrieve and display relevant data from the Redux store in your functional components.