How to build a Fabulous Todo App using React, Redux and Framer-Motion
Published: 2023-02-13 07:21:30

Hey,

I know building TODO List always won't get you too far😴, But It can teach you basic concepts and implementation of particular framework.

here is the demo of what we're going to build in this tutorial.👇👇
Link: https://react-redux-todo-app-lac.vercel.app/

Now please if you're starting this tutorial watch till the end because doing it half won't teach you anything. So let's dig in.🤩

In this tutorial we're going to build this TODO app with animations using Framer-Motion.

What will you learn after this Tutorial?


-How to use Redux Toolkit
-How to use Framer-Motion for awesome animations
-Method to sort and display lists
-CRUD operation (obviously🤭)

You must have basic understanding of Redux to follow this tutorial, don't worry if you don't know the basics of Redux you can visit my channel, there is playlist to learn redux.

Let's get Started
First, The below is the folder structure for this small project so make sure you create it.

**Folder Structure**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/trjuoacmkmkt3aui977t.png)
Follow below commands to create react-app and install required libraries!

**npx** create-react-app your-app-name
cd your-app-name
**npm** install react-redux @reduxjs/toolkit framer-motion react-icons

we're going to use these all four libraries,
react-icons is to add svg files in our app.

First let's add one input and add button in the Todos.js.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/soxek7bxfmd6t3f0wq0b.png)
As you can see in above code it has one input with handleChange() method and one add button.

Creating Reducer and Store
Now let's create our Reducer and actions.
Open reducer.js file and write below code:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rrkzks4tzsnc57gmhwzn.png)

Explanation:

Now here we're going to use createSlice() function.
This function takes 1 object having 3 parameters,
--> name of the slice function
--> initial State
--> All reducer logic inside reducers {} object

Line 1: import createSlice function.

Line 2: create initial state here it is an empty array.

Line 5: Here we have used createSlice function and passed all 3 required parametrs.

Line 13: We have created one action called addTodos this action get an callback function which have two arguments (state, action). Then this function will return state with adding action.payload (payload contains one todo item).

Line 22: Here we have exported addTodos as action from addTodoReducer.

Line 23: Here we have exported reducer from addTodoReducer.

So, let's create our store and pass this reducer.

Open store.js and write below code:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q0p89cweu885meq8fxgn.png)

In the above code we have used configureStore function.

This funcion takes one reducer and automatically takes care for the Redux DevTools extension so we don't have to write about it explicitly.

Now our store is ready with reducer that we have created.

Connecting Redux Store with React App
Let's connect this store to our React application.

I like to connect store in the index.js file.
Open index.js file.

import Provider from the react-redux and store from store.js

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/swrmpy72xqifxoligf3j.png)

Now just wrap your component with this Provider and pass store in the Provider just like this,

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/90jt4pmi9buocm0wzmhm.png)
Now our Redux store is connected with our React App.

Connect React component with Redux
Let's use this store and Redux functionalities in the Todos.js component.

To connect this component with Redux we will use connect() method from react-redux.

Open Todos.js file.

import connect method from react-redux.
import { connect } from "react-redux";
Now instead of simple export default Todos change it to this line:
export default connect(null,null)(Todos);
This is how we use connect method, It's like higher order function that takes your component (Todos in our case) and add redux functionalities to it then return it.

Now add props in your component and log this props you will see and Object having dispatch method. Which means your component is now connected with Redux.

Let's use todos state in our component.

To use state from redux we have to pass mapStateToProps method in the connect method.
and to use actions or functions that we created inside the reducer (like addTodos) we have to create and pass mapDispatchToProps method and add it to the coonect method.

So let's create both of this methods in the Todos.js component.
const mapStateToProps = (state) => {
  return {
    todos: state,
  };
};
This method takes state as argument and will return state as we want here i want state as todos.
const mapDispatchToProps = (dispatch) => {
  return {
    addTodo: (obj) => dispatch(addTodos(obj)),
  };
};
This method takes dispatch as argument and it can dispatch action to reducer.
here, I want to add todos so this method returns and addTodo method.
addTodo method dispatch an addTodos action with an obj(which contains todo item, it will acts as action.payload ).

here, make sure to import addTodos action from reducer file.

now add both of this methods in the connect just like this,
export default connect(mapStateToProps, mapDispatchToProps)(Todos);
let's connect input and add button with this state and methods.


import React, { useState } from "react";
import { connect } from "react-redux";
import { addTodos } from "../redux/reducer";

const mapStateToProps = (state) => {
  return {
    todos: state,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    addTodo: (obj) => dispatch(addTodos(obj)),
  };
};

const Todos = (props) => {
  
  console.log("props",props);
  
  const [todo, setTodo] = useState("");
  
    const add = () => {
    if (todo === "") {
      alert("Input is Empty");
    } else {
      props.addTodo({
        id: Math.floor(Math.random() * 1000),
        item: todo,
        completed: false,
      });
      setTodo("");
    }
  };
  

  const handleChange = (e) => {
    setTodo(e.target.value);
  };

  return (
    <div className="addTodos">
      <input
        type="text"
        onChange={(e) => handleChange(e)}
        className="todo-input"
        value={todo}
      />

      <button className="add-btn"  onClick={() => add()}>
        Add
      </button>
      <br />
      
      <ul>
        {props.todos.length > 0 &&
          props.todos.map((item) => {
            return <li key={item.id}>{item.item}</li>;
          })}
      </ul>
        
    </div>
  );
};
Line 23: Here I have created add function. First it will check it todo state is not empty if it is empty then shows an alert else it will use addTodo method from props.
in this method we will pass todo object which contains
id, todo text, completed boolean which is initially false.

Line 50: Make sure to connect add() with onClick of button.

Line 55: here I have mapped values from todos state.
If todos.length > 0 then it will map it and shows all todo items you add.