Starting with React-Redux
Tags: react, redux, webdev, beginners
Published: 2021-11-21 14:45:55

Hello everyone, this is my first post on **Dev.to**. In this post, I am trying to explain the use of **Redux** in ReactJS with an example. Here, I have taken some references from YouTube and Google for information. I will first explain to you the need for **Redux** and explain it with the code. For reference, you can check out Github to view the code anytime.

[View Live Demo](https://redux-starter-boilerplate.herokuapp.com/)            

[View on Github](https://github.com/mohitm15/redux-boilerplate/tree/master/redux-boilerplate)



## Why do we need Redux ?

When a JavaScript Application grows big, it becomes difficult to manage its **state**. For example, in the given architecture, if I want to use the state defined in Child_C of the Contact.js in the Child_B of the Home.js, then I had to do **prop-drilling**, where I have to pass the **state** as props over various components.

![Prop-drilling in ReactJS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ugzngpwex7cxfc74n40.png)

But Redux solves this problem by managing the application's state with the help of a single global object called `Store.` This provides consistency to the application and makes testing easy.

##Redux -Architecture

The Architecture consists of **4 components** mainly - `Action, Reducer, Store and View`. And believe me, they work in the same way as their name suggests.

![Redux Architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rm42cl1lpmqwjlya0qn0.png)

- Action is a plain object that describes the intention to cause change, like adding or deleting a task in a To-do-List app.
- Reducer is a function that determines changes to an application state. Like in the To-do-List app, action will trigger a change in the value of state `task_Array` that the reducer will determine. It returns the new state and tells the store how to do it. Simply, it uses the action it receives to determine the change.
- Store projects all the state variables to the view, which is the UI of the application.


Now, let's make our hands dirty and start coding with an example to understand **Redux** more deeply. I will tell you the concept and later, you can start with your stuff to do with it. Also, I have added some tasks for deep understanding in the end.

##Example - Redux Boilerplate.

Here we try **to create a webApp where we define the states in different components and perform onclick events from different components. The states we define are the `countValue` and `darkMode` enabling.**

If you directly want to see the whole code, you can view it on Github. :cowboy_hat_face:

[View on Github](https://github.com/mohitm15/redux-boilerplate/tree/master/redux-boilerplate)

###1. Setting Up React App

Create a folder in your desktop named `redux-boilerplate` and open it in the **VSCode**. Now, open the terminal and create the react app.

` npx create-react-app redux-boilerplate `

>**Note**: You’ll need to have Node >= 14.0.0 and npm >= 5.6 on your machine.

Now add the Bootstrap by using the CDN link of CSS ([here](https://getbootstrap.com/docs/5.1/getting-started/introduction/#css)) and script link ([here](https://getbootstrap.com/docs/5.1/getting-started/introduction/#js)) .

If you are new , just simply copy the `<link>` and `<script>` from both the links and paste it to the **public>>index.html** file at appropriate place.

> **ProTip:**To check bootstrap added successfully, just simply paste the code to `App.js` file and see red colored font.
> ```
import './App.css';
function App() {
  return (
    <>
      <h1 className="text-danger"> Hello World!</h1>
    </>
  );
}
export default App;
```

##2. Creating NavBar and Shop Component

Create a folder **components** in `src` folder. Now create a file `Navbar.js` & another file `Shop.js` both in components folder.

####NavBar.js
```
import React from "react";

const Navbar = () => {

  return (
    <div>
      <nav className="navbar navbar-expand-lg navbar-dark bg-dark">
        <div className="container-fluid">
          <a className="navbar-brand" href="/">
            Redux BoilerPlate
          </a>
          <button
            className="navbar-toggler"
            type="button"
            data-bs-toggle="collapse"
            data-bs-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent"
            aria-expanded="false"
            aria-label="Toggle navigation"
          >
            <span className="navbar-toggler-icon"></span>
          </button>
          <div className="collapse navbar-collapse" id="navbarSupportedContent">
            <ul className="navbar-nav me-auto mb-2 mb-lg-0">
              <li className="nav-item">
                <a className="nav-link active" aria-current="page" href="/">
                  Home
                </a>
              </li>
              <li className="nav-item">
                <a className="nav-link" href="/about">
                  About
                </a>
              </li>
            </ul>
          </div>
          <div>
             
                <div className="form-check form-switch mx-4">
                  <input className="form-check-input" type="checkbox" id="flexSwitchCheckDefault" />
                  <label className="form-check-label text-light" htmlFor="flexSwitchCheckDefault">Darkmode</label>
                </div>
            </div>
          <div>
            <button className="btn btn-info mx-1">CountValue : 0 </button>
          </div>
        </div>
      </nav>
    </div>
  );
};

export default Navbar;

```


####Shop.js


```
import React from 'react';

const Shop = () => {
    
    return (
        <>
        <div className="container p-3"> 
        <div className={`alert alert-success` } role="alert">
            <h2>Redux BoilerPlate</h2>
        </div>
            <h3 className="my-5">Simple Starter template for redux-store</h3>
            
            <div className="container my-5">
                <h1 className="display-1">This is LightMode</h1>
            </div>

            <div className="container d-flex">
                <button className="btn-lg btn-success mx-4" > + </button>
                    <h1 className="display-6">You Count Value = 0 </h1>
                <button className="btn-lg btn-danger mx-4" > - </button>
            </div>
        </div>
        </>
    )
}

export default Shop;


```


Paste the above code in **Navbar.js** & **Shop.js** respectively .Add the components in **App.js** using

```
import Navbar from './components/Navbar';
import Shop from './components/Shop';
.
.
.
  return (
    <>
      <Navbar />
       <div className="container p-3">
        <Shop />
      </div>
    </>
  );
}
```
This will show the navbar at top and Shop component on screen.


###3. Installing Redux

To install the redux , just open a new tab in terminal and run 
          `npm i redux`
          `npm i react-redux`
          `npm i redux-thunk`

> *Get more info [here](https://www.npmjs.com/package/redux) .*


###4. Creating Action-Creator and Reducers

Now we'll create action-creators and reducers function which will change the `countValue` and enable `darkMode`.

> *As discussed, action-creators create the action to change the state variable and reducer is a pure function that takes action & the previous state of the application and returns the new state.*

Action consists of *type* and *payload* to be supplied to Reducer function. The type defines the action-type and the payload defines the value to be substituted with the previous one.

To do this, we will create a folder name `state` inside the `src` folder. Inside the `src` folder, we create two more folders :
- action-creators
- reducer

![directory structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/39n9pch22sbsmfjn9625.png)

Now we create `index.js` file in `action-creators` folder and write code for action-creator. We will create action here.

```
export const increaseCount = (countValue) => {
    return (dispatch) => {
        dispatch ({
            type: 'increase',
            payload: countValue
        })
    }
}

```
Here, **increaseCount** is a function that returns a function named `dispatch` which dispatches type & payload.  

Try to write action-creators for `decreaseCount`, `enableDarkMode` and `enableLightMode` in the same file.

You can compare your code with the full code of `state/action-creators/index.js` from [here](https://github.com/mohitm15/redux-boilerplate/blob/master/redux-boilerplate/src/state/action-creators/index.js).


Now we make `Reducers`. Reducers need not to be a single one, for the different states, we have different reducers. Like here, we'll create two reducers file named `countReducer.js` and `darkmodeReducer.js` inside `reducer` folder, which will look after the `countValue` and `darkMode` state variables.

Let's create `countReducer.js` to change the count value.

```
const reducer = (state=0, action) => {
    if(action.type === 'increase') {
        return state +  action.payload;
    }
    else if(action.type === 'decrease') {
        return state - action.payload
    }
    else {
        return state;
    }

}

export default reducer;

```

As you can see above, it takes the state variable and action from the action creator as a parameter and returns the modified state with the help of the action payload.

Try to create `darkModeReducer.js` by own first and compare your results from below.


```
const reducer = (state= 'OFF', action) => {
    if(action.type === 'darkmode') {
        state = action.payload;
    }
    else if(action.type === 'lightmode') {
        state = action.payload;
    }
    return state;
}

export default reducer;
```

####Bonus 

Since for large complex applications, we know that we require many reducers and handling them individually is a messy task. So redux provides us [`combineReducers`](https://redux.js.org/api/combinereducers), which combines all the reducer functions and export them as a single reducer function.

For this, create a file `index.js` in `reducer` folder and paste the below code.

```
import { combineReducers } from "redux";
import countValueReducer from './countReducer';
import darkmodeReducer from './darkmodeReducer';

//combinnig all the reducers here
const reducer = combineReducers({
    countValue: countValueReducer,
    darkmode: darkmodeReducer
})

export default reducer;     
```

###5. Creating Store

To recall, a store is a global place where all the things defined is exposed to all the application. Simply, every part of the application gets access to the store.

Here, we will create a file `store.js` inside the `state` directory. Use to code below for `store.js`.

```
import { applyMiddleware, createStore } from "redux";
import thunk from "redux-thunk";
import reducer from "./reducer";

export const store = createStore(reducer,{}, applyMiddleware(thunk));

```
You have seen many new things here, let's understand them one by one.

- **[createStore](https://redux.js.org/api/createstore)** : It takes the reducers, preloaded state and enhancer function(optional) to create the store. It returns an object that holds the complete state of your app.

- **[applyMiddleware](https://redux.js.org/api/applymiddleware)** : Returns a store enhancer that applies the given middleware.

- **[redux-thunk](https://github.com/reduxjs/redux-thunk#readme)**: Helps to execute asynchronous functions.

Hurray! store is created. :sparkles:

Now I want to give access of store to the overall application. So we go to the file `src/index.js` (main index.js file) and import the store here. The file will look like 

```
import React from 'react';
.
.
.
import { Provider } from 'react-redux';
import { store } from './state/store';

ReactDOM.render(
 .
 .
    <Provider store={store}>
    <App />
    </Provider>
 .
 .
);

```
See complete file [here](https://github.com/mohitm15/redux-boilerplate/blob/master/redux-boilerplate/src/index.js).

Also we create a file `index.js` inside `state` directory.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xcgi898gvhcwvrczu0mp.png)

This will increase the accessbility of action-creators as we export all the action-creators from here to all the components like *Navbar.js*.

```
export * as actionCreators from './action-creators/index';

```

###6. Second Last Step

As far as now, we have not added any function to the `+`/ `-` button and `darkmode` toggle, but now we got access to the state variables through store, we can use them to display their values on the UI.


To access the state, we use [`useSelector`](https://react-redux.js.org/api/hooks#useselector) hook. In the `navbar.js` file we import the hook first using 
```
import { useSelector } from "react-redux";
```
and then use it as
```
.
.
 const countValue = useSelector((state) => state.countValue);
 const darkmode = useSelector((state) => state.darkmode);
.
.
```
And change the value of countValue from `0 to {countValue}`, like this

```
<button className="btn btn-info mx-1">CountValue : {countValue}</button>
```

So far we have use the countValue state, we also need to use `darkMode` state in `App.js` and `Shop.js`.

####App.js
```
import { useSelector } from "react-redux";
import './App.css';
import Navbar from './components/Navbar';
import Shop from './components/Shop';

function App() {

const darkmode = useSelector(state => state.darkmode);

let darkmodeStyle = {
        backgroundColor:'#2d2d2d',
        color:'whitesmoke'
    }

  return (
    <>
      <Navbar />
      <div className="container p-3" style={darkmodeStyle}>
        <Shop />
      </div>
    </>
  );
}

export default App;
```
In `shop.js`, just simply import the `useSelector` hook like in `Navbar.js` using
```
import { useSelector } from "react-redux";
```
and then use it as inside `Shop` component.
```
.
.
 const darkmode = useSelector((state) => state.darkmode);
.
.
```

###7. Last Step 

Now we have access to the variables that we use to bring the changes on view.

Here, state values will be first changed by the user from the front-end. Then, we need to generate those actions, which triggers reducer functions and finally alter the values of the state on view.

To do this we use [`useDispatch`](https://react-redux.js.org/api/hooks#usedispatch) hook, which dispatches the action-creators and [`bindActionCreators`](https://redux.js.org/api/bindactioncreators) to bind all action creators.

Time to use them!

In `Navbar.js` and `Shop.js`, import them as
```
import { useSelector, useDispatch } from "react-redux";
import { bindActionCreators } from 'redux';
import { actionCreators } from '../state/index';
```
And in `Navbar.js`, we use `enableDarkMode` action-creator to dispatch.

```
const dispatch = useDispatch();//to dispacth the action creator functions
  const {enableDarkMode} = bindActionCreators(actionCreators, dispatch);
```
We will add this `darkMode` functionality to **toggle button** present in navbar like this

```
<input className="form-check-input" onClick={()=>{darkmode === 'OFF'?enableDarkMode('ON'):enableDarkMode('OFF')}} type="checkbox" id="flexSwitchCheckDefault" />
```
And add the styling in the `App.js` as

```
.
.

const darkmode = useSelector(state => state.darkmode);
let darkmodeStyle = {}

if(darkmode === 'ON') {
    darkmodeStyle = {
        backgroundColor:'#2d2d2d',
        color:'whitesmoke'
    }
}

  return (
    <>
.
.
```
Also change a **div** component in `Shop.js` to switch the title on the main page from `LightMode` to `DarkMode`.

###Shop.js

```
<div className="container my-5">
                <h1 className="display-1">This is {darkmode === "ON" ? "DarkMode" : "LightMode"}</h1>
            </div>
```

*Now you will be able to change background color.*

![darkMode GIF](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d13blemrjcym6o6k69be.gif)

To use `countValue` action-creator to dispatch,  we need to code in `Shop.js`.
```
const dispatch = useDispatch();
const balance = useSelector(state => state.countValue);
const {increaseCount, decreaseCount} = bindActionCreators(actionCreators,dispatch);
```

We will add this `increaseCount/decreaseCount` functionality to **+ and - buttons** present in screen like this.

```
<div className="container d-flex">
                <button className="btn-lg btn-success mx-4" onClick={()=>(increaseCount(1))}> + </button>
                    <h1 className="display-6">You Count Value = {balance} </h1>
                <button className="btn-lg btn-danger mx-4" onClick={()=>(decreaseCount(1))}> - </button>
            </div>
```

*Now you will be able to change the countValue.*

![countValue GIF](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wr8qd9e8y9qfbrmcz6qm.gif)

For reference,
Complete Navbar.js file is [here](https://github.com/mohitm15/redux-boilerplate/blob/master/redux-boilerplate/src/components/Navbar.js).
Complete Shop.js file is [here](https://github.com/mohitm15/redux-boilerplate/blob/master/redux-boilerplate/src/components/Shop.js).
Complete App.js file is [here](https://github.com/mohitm15/redux-boilerplate/blob/master/redux-boilerplate/src/App.js).


### Conclusion

Cheers! :beers:, you have build the basic template for redux. Now you can come up with as many functionalities and components to the application. You can take up some challenges by trying tasks like adding a login page, displaying the profile page, or categorizing the type of users. 

Try to come up with your own ideas and send the PRs over [here](https://github.com/mohitm15/redux-boilerplate/tree/master/redux-boilerplate).

Thank you for your time. Since this is my first post, please share your valuable feedback in comments also.

Happy Coding ! :shamrock: