Step by Step Guide in Understanding Redux and Redux ToolKit.

Table of contents

No heading

No headings in the article.

Hi there,

Grasping the concept of redux and reduxtoolkit has always been a struggle for react developers at the initial stage of learning, so I'm going to write a small series on the simplest method to understand how redux and reduxtoolkit works.

image.png

image.png

As previously stated, this will be a series, and the following is the table of contents for what we will be learning:

  1. Introduction to Redux
  2. Connecting React and Redux
  3. Combining Reducers in Redux
  4. Redux Debugging with Redux Dev Tools
  5. Introduction to ReduxToolkit and its Usage

In this article, I will be talking about why we need redux and what problem does it solve exactly.

Prerequisite: React Hooks (esp useReducer).

Let's go...

THE PROBLEM

Say we have a simple react application that has its folder structure as the image below:

image.png

The parent component is : App.js

4 Child Components: Home.jsx, About.jsx, Services.jsx, Contact.jsx

2 sub-child components belonging to Services component: SellData.jsx and BuyData.jsx

Now, assuming we fetched data into Services.jsx from an API endpoint, this data can be easily used in its child components (Sell and Buy Data).

image.png image.png

Now the problem occurs when any of the neighbour components of Services.jsx i.e Home, About and Contact needs to access that data we fetched initially.

image.png

A quick way around this is by lifting the state in the Services.jsx file into the Parent component: App.jsx file, where the state holding the data can be used by all the neighbouring components.

image.png

But this is not an efficient way to manage states especially if you are working on a large scale project.

The best way to solve this problem is to take out the state from the components tree and make it centralized so that any component in the tree can access and update the state without worrying about the hierarchy in the tree. This is the basic idea behind redux, a single centralized place to contain the global state in your application and specific patterns to follow when updating the state.

THE SOLUTION REDUX!!!. Redux can be used to store the state and can use it to any component without worrying about the hierarchy i.e the neighbouring component needing state data from another.

So how does react state works without redux? Let's use a counter app as an example.

import { useState } from "react";
import "./styles.css";

export default function App() {
  // this is the state managing our counter
  const [counter, setCounter] = useState(0);


  // function to fire an increase or decrease event
  const handleIncrease = () => {
    setCounter((counter) => counter + 1);
  };

  const handleDecrease = () => {
    setCounter((counter) => counter + 1);
  };
  return (

    // UI to hold the buttons, so that when the button is clicked the value on the counter on the UI increases or decrease based on the user's preference.
    <div className="App">
      <div className="counter">{counter}</div>
      <button onClick={handleIncrease}>Increase</button>
      <button onClick={handleDecrease}>Decrease</button>
    </div>
  );
}

The action/event acts as a trigger to update the state from 0 to either + 1 or -1 depending on the button clicked. Then when the state changes it is then updated to a new state and the UI is re-rendered based on the current state.

image.png

So what happens when you use redux?

image.png

In redux, we have a function called REDUCER. It takes in two arguments, which are: the state itself and the action object. Action objects can have a type of action like increment or decrement to modify the state. So say we have our state defined to be 0 initially, based on the initial state value (0) and action type (increment/decrement), redux calculate a new value for the state and updates it. All these things happen in where we call a REDUX STORE a centralized database for state management.

Now let's see this in practice to understand better:

create a new react app using :

npx create-react-app redux-tutorial

Once it is done, inside the index.js file we start writing the redux logics.

First, we import createStore from the redux package and create our initial state which will be set to 0.

import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import App from "./App";

// initial state just like [counter, setCounter] = useState(0) in normal react
const initialState = {
  counter: 0
};


const rootElement = document.getElementById("root");
ReactDOM.render(
  <StrictMode>
    <App />
  </StrictMode>,
  rootElement
);

Then we will create a reducer function called counterReducer. This will take 2 argument as we mentioned previously, state and action. The action event will be specified, which will be: if its 'increment'? then increase the counter:0 we defined initially by 1 other wise if it is 'decrement' reduce it by 1, then we return the state.

NB: Always return your state once you finish writing your action events.

The createStore we imported earlier will then be stored in a variable called 'store' which will take the counterReducer as the argument.

import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";
import App from "./App";

// initial state just like [counter, setCounter] = useState(0)
const initialState = {
  counter: 0
};

// reducer function
const counterReducer = (state = initialState, action) => {
// action event logic
  if (action.type === "increment") {
    return { counter: state.counter + 1 };
  } else if (action.type === "decrement") {
    return { counter: state.counter - 1 };
  } else {
    return state;
  }
};

// storing the counterReducer function inside the createStore. 
const store = createStore(counterReducer);

console.log(store.getState());
const rootElement = document.getElementById("root");
ReactDOM.render(
  <StrictMode>
    <App />
  </StrictMode>,
  rootElement
);

Now if we console.log the store we have these methods:

image.png

getState() is used to get our state(initial state defined) which is 0.

image.png

dispatch() is to dispatch an action type which in our case is 'Increment or decrement '

so say we dispatch 'Increment' which will increase initialState by 1 i.e 0 + 1 = 1

store.dispatch({
   type: "increment"
 });

console.log(store.getState())

image.png

If we dispatch 'Decrement' same process will occur. Remember the current state now is 1 from increment, so what will this dispatch function give us? 1-1 = 0

store.dispatch({
   type: "decrement"
 });

console.log(store.getState())

image.png

The subscribe method allows us to console.log any changes that occur without having to type console.log after everytime we dispatch an action.

store.subscribe(() => console.log("Store was updated and now is:", store.getState()));

So this shows in the console whenever any action type is dispatched.

This is where we stop for this introduction and for the next article I will be talking about CONNECTING REDUX TO REACT

Thank you for your time😀...See you around next time

Cheers.