DEV Community

Cover image for React Redux | Learn the redux easily with project
Anuj Singh
Anuj Singh

Posted on

React Redux | Learn the redux easily with project

💥💥 React Redux Example 💥💥

This is a todo project for understanding the concepts of redux in react, this github project is referenced in this project

What is Redux ?

Redux is used for state management for the application. It's main advantage is to overcome the problem of "props drilling" among the components.

For example, Let's assume we have 4 component named A,B,C,D and their representation is like :
A ( Parent Component )
|
B
|
C
|
D ( Leaf Component )

and we have a prop named itemCode which is generated at component A, and only to be used at component D.
Traditional Way was to pass that itemCode as an prop to B, then C, and at last to D.

😎😎 How Redux Solves is that it makes an store for an application, which holds all the states of application at one place. So when itemCode is generated at component A, insted of passing it as an props to all the way down to component D, component A will store that itemCode in the Store, and component D will fetch itemCode value form that Store.

Note, But what's the problem in props 🙄🙄 ?
This todo application is very small scale project, in large projects, this props count be large like 10, 20, 100 anything, so using props everywhere will be make the application very very complex 🤯🤯🤯

Let's drive deep into working of Redux

First let's setup the basic project

  1. Create new react project npx create-react-app todo_redux
  2. Install redux dependencies npm install react-redux redux
  3. Make an folder named action and reducer in /src
  4. Inside action folder, make 2 files, /action-types.js and /todo.js
  5. Inside reducer folder, make file named /todo.js
  6. And in /src folder a file, make a file named store.js

After this your project heirarchy will look like :
Alt Text

But what are these Action, Reducer, and Store ?

💥💥 Actions 💥💥 :

It contains the logic that will tell Reducer what should be done on calling specific commands which developer has made. Like in our case, their are 2 action which is made,

  1. Add Todo
  2. Remove Todo

So, Action will tell Reducer that, Okay so there is an call from component to Add Todo, So Hey Reducer, we now have to Add an todo with this that details.

Syntax for Action :

import { ADD_TODO } from "./action-types";
export const addTodo = (todo) => ({
  type: ADD_TODO,
  payload: todo,
});
Enter fullscreen mode Exit fullscreen mode

addTodo is a name of the package which return object with a compulsory field **"type"** and optional field "payload".

  1. Type : It is used to validate action on reducer side that okay an action of type blah blah 😜 type is recieved and I have to perform logic related to this blah blah 🙈 only
  2. Payload : Sometimes on the reducer side, some data is sent which is used to update the state in the store.

💥💥 Reducer 💥💥 :

So till now we have an action which states what to do, but how to do ? is defined in reducer file. For our case, what to do with the state/store when an addTodo action is recieved == We have to add an todo with details recieved from action package into out store which has some previous todos and return the updated state of todos in out store.

Syntax for Reducer

import { ADD_TODO } from "../action/action-types";
const initialState = [];
export const todos = (state = initialState, action) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, action.payload];
    default:
      return state;
  }
};
Enter fullscreen mode Exit fullscreen mode

See here the types field of action comes into play, to validate what logic is to be performed when an certain type of action is called. And payload data to update the state/store.

There can be many files containing multiple reducers, but at the end we will combine all the reducers from all the files into one root reducer, because the store expects only one reducer. ( we will see how to do that later in this article )

💥💥 Store 💥💥 :

Store is the place where all the states of an application is kept. Store is readonly , for updating, we can only do it through reducer
And also, for an whole application, there will be only 1 store.

Syntax for Store

import { createStore, combineReducers } from  "redux";
import { todos } from  "./reducer/todo";
const  rootReducer = combineReducers(
    todos
});
const  store = createStore(rootReducer);
export  default  store;
Enter fullscreen mode Exit fullscreen mode

Here we import all the reducer file and with the help of combineReducers we combine them into 1 reducer and with createStore we create an store for the application.

So till now we have made an Store with root reducers combining all the reducers, Action which tells what to do and Reducer which tells how to do. Now the question is how to access store from component ? 🤷‍♀️🤷‍♀️🤷‍♀️

Firstly we have to wrap the main parent component inside App.js with
<Provider store={store}> all the components comes here </Provider >

Provider is react-redux magic which handles all the work and store is passed it, which is imported from store file.

Now connecting component to store ✌✌ :

We have to use 2 function which will fetch and sent the data to store through action then reducers all that flow.

Introducing :

mapStateToProps( ) 🤑🤑:

This function is used to fetch the data from store and pass it as a prop to the component, and from then onwards in the component it is used as traditional way like using value from props.

Syntax for mapStateToProps()

const mapStateToProps = (state) => ({
  todos: state.todos,
});
Enter fullscreen mode Exit fullscreen mode

and in component, it will be accessible as props

const TodoForm = ({ todos }) => {};
Enter fullscreen mode Exit fullscreen mode

mapDispatchToProps ( ) 😁😁:

This function is used to prepare action package which will later on go to reducer to update the state of the application. For example in our case, we have to add todo with todo detail so we have to prepare action of type addtodo

Syntax for mapDispatchToProps ()

const mapDispatchToProps = (dispatch) => ({
  addTodo: (todo) => {
    dispatch(addTodo(todo));
  },
});
Enter fullscreen mode Exit fullscreen mode

and in component, it will be accessible as props

const TodoForm = ({ addTodo }) => {};
Enter fullscreen mode Exit fullscreen mode

All Done 🙌🎉🎉

Thank You for reading it 🤗🤗 Hope you like it.

Top comments (2)

Collapse
 
phutngo profile image
Phu Ngo

Genuinely curious, besides having to work on older codebases, why use redux when zustand can do the same thing in half the lines of codes and half of the time to do it?

Collapse
 
italoec profile image
Italo Alves

I don't know zustand in depth, but, beyond redux be the default choice in professional applications, redux brings much more possibilities than only state management. For example redux thunk, redux sagas, redux persist.. this libs offer ways to remove the logic out of the component files, and this improove the organization of the codebase