Todo with React,Redux,React Hooks
Tags: react, javascript
Published: 2021-09-09 11:27:57

Let’s get started what functionality we going to add in this step by step:

1. Adding Task to List
2. Deleting Task or Multiple
3. Changing the status of Task
4. Updating the Task

Let first Create our create app with command:

```javascript
create-react-app todo
```

Now Open the todo in code editor, currently Folder structure look like this.

![Screen Shot 2021-09-09 at 9.09.44 AM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o77cmz1ehojgwcl7mxvw.jpg)

Open the App.js where we will write our todo's code.

First we create the input with a button where we will try to add the task to the list.
![Screen Shot 2021-09-09 at 9.14.19 AM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h1vm0my602moce256826.jpg)


```javascript
import React, { useState } from "react";
import "./App.css";

function App() {
  const [input, setInput] = useState("");

  return (
    <div className={container}>
      <form>
        <input className={input} type="text" value={input} onChange={(e) => setInput(e.target.value)} />
        <button className="createbtn btn" type="submit">
          Create
        </button>
      </form>
    </div>
  );
}
export default Todo;

```
We will go from first line, in the first line we have imported the `React, {useState}`. here we have imported react library and the useState, which we use to manage the State in functional component.

Now if move to next, first we have created a state for our input `const [input, setInput] = useState("");`

In the return we have written our JSX for input and button. 


For css you can paste this in `App.css`.

```css
.container {
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.form {
  border: 1px solid;
  padding: 15px;
}

.btn {
  background-color: white;
  color: black;
  font-size: 16px;
  cursor: pointer;
}

.input {
  width: 230px;
  height: 30px;
  border-radius: 5px;
  padding-left: 10px;
  margin-top: 10px;
  margin-bottom: 10px;
}

.createbtn {
  border: 1px solid #fff;
  font-size: 18px;
  color: rgb(255, 60, 0);
  padding: 7px 20px;
  border-radius: 5px;
  margin-left: 25px;
}

.statusbtn {
  border: none;
}

.statusbtn:hover {
  color: red;
}

.deleteContainer {
  position: relative;
}

.deletebtn {
  margin-top: 15px;
  color: red;
  border: 1px solid;
  position: absolute;
  right: 0px;
}

.todotable {
  font-family: Arial, Helvetica, sans-serif;
  border-collapse: collapse;
  min-width: 600px;
  margin-top: 10px;
}

.todotable td,
.todotable th {
  border: 1px solid #ddd;
  padding: 8px;
}

.todotable tr:nth-child(even) {
  background-color: #f2f2f2;
}

.todotable tr:hover {
  background-color: #ddd;
}

.todotable th {
  padding-top: 12px;
  padding-bottom: 12px;
  text-align: left;
  background-color: #434546;
  color: white;
}

.updatebtn {
  border: 1px solid #fff;
  font-size: 18px;
  color: rgb(255, 60, 0);
  padding: 7px 20px;
  border-radius: 5px;
}

.createbtn:hover,
.updatebtn:hover {
  border: 1px solid;
}

```

Now we will create a Table for showing our Task, 
so we will some modification in our `App.js`.

```javascript
import React, { useState } from "react";
import "./App.css";

function App() {
  const [input, setInput] = useState("");
  const [selectedItem, setSelectedItem] = useState([]);

  const handleSubmit = () => {
  };

  const handleUpdate = () => {
  };

  const handleCheckbox = () => {
  };

  return (
    <div className="container">
      <form onSubmit={handleSubmit}>
        <input className="input" type="text" value={input} onChange={(e) => setInput(e.target.value)} />
        <button className="createbtn btn" type="submit">
          Create
        </button>
      </form>
      <div>
        <table className="todotable">
          <tbody>
            <tr>
              <th></th>
              <th>My Todo List</th>
              <th>Status</th>
            </tr>
                <tr>
                  <td>
                    <input type="checkbox"/>
                  </td>
                  <td>
                    Title
                  </td>
                  <td>
                    <button className="statusbtn btn">
                      Change State of Task
                    </button>
                  </td>
                </tr>
          </tbody>
        </table>
        <div className="deleteContainer">
          <button className="deletebtn btn">
            Delete items
          </button>
        </div>
      </div>
    </div>
  );
}

```

Now we will move to add redux, for using first we will install the required dependencies.

```javascript
npm i redux react-redux --save
```

We will start integrating the redux into our app.
Now we create a folder named `redux`. Inside of that we will create four files parallely named `action.js`,`reducer.js`, `store.js`,`actionTypes`. You folder structure will look like this.

![Screen Shot 2021-09-09 at 4.41.28 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/63vexla9ccnw50kthyxm.jpg)


Now we will write code inside `store.js`

```Javascript
import { createStore } from "redux";
import reducer from "./reducer";

const store = createStore(reducer);

export default store;
```

Now we will write code inside `action.js`
```Javascript

import { ADD_TODO, DELETE_TODO, UPDATE_TODO } from "./actionTypes";

export const addTodo = (payload) => {
  return {
    type: ADD_TODO,
    payload: payload,
  };
};

export const updateTodo = (payload) => {
  return {
    type: UPDATE_TODO,
    payload: payload,
  };
};

export const deleteTodo = (payload) => {
  return {
    type: DELETE_TODO,
    payload: payload,
  };
};
```

Now we will write code inside `reducer.js`
```Javascript
import { ADD_TODO, DELETE_TODO, UPDATE_TODO } from "./actionTypes";

const initialState = {
  todos: [
    { id: 0, title: "Learn React", completed: true, description: "We need to learn react from basic to advance in 2 months" },
    { id: 1, title: "Learn Redux", completed: false, description: "We need to learn redux after react from basic to advance in 15 days" },
    { id: 2, title: "Build something fun!", completed: false, description: "We need to build a project based on react and redux " },
  ],
};

const returnUpdatedState = (state, action) => {
  return {
    ...state,
    todos: action.payload,
  };
};

function reducer(state = initialState, action) {
  switch (action.type) {
    case ADD_TODO: {
      // Can return just the new todos array - no extra object around it
      console.log(console.log(state));
      return {
        ...state,
        todos: [
          ...state.todos,
          {
            id: state.todos.length,
            title: action.payload,
            desc: "hello",
            completed: false,
          },
        ],
      };
    }
    case DELETE_TODO:
      return returnUpdatedState(state, action);
    case UPDATE_TODO:
      return returnUpdatedState(state, action);

    default:
      return state;
  }
}

export default reducer;
```

Now we will write code inside `actionTypes.js`
```Javascript
export const ADD_TODO = "ADD_TODO";
export const UPDATE_TODO = "UPDATE_TODO";
export const DELETE_TODO = "DELETE_TODO";
```

We need to some modifications in `index.js` for configuring the redux to react App.

```Javascript
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import { Provider } from "react-redux";
import store from "./redux/store";

ReactDOM.render(
  <Provider store={store}>
      <App />
  </Provider>,
  document.getElementById("root")
);

```

Now if we move to the App.js for adding the redux.
it will look something like this.

```Javascript
import React, { useState } from "react";
import { connect } from "react-redux";
import { addTodo, updateTodo, deleteTodo } from "../redux/actions";
import { Link } from "react-router-dom";
import "./App.css";

function App(props) {
  const [input, setInput] = useState("");
  const [selectedItem, setSelectedItem] = useState([]);

  const handleSubmit = (e) => {
    e.preventDefault();
    if (input) {
      props.addTodo(input);
    }
  };

  const handleUpdate = (id) => {
    let getTodo = props.todos.map((e) => {
      if (e.id === id) {
        return { ...e, completed: !e.completed };
      }
      return e;
    });
    props.updateTodo(getTodo);
  };

  const handleCheckbox = (id) => {
    if (!selectedItem.includes(id)) {
      setSelectedItem([...selectedItem, id]);
    } else {
      setSelectedItem(selectedItem.filter((e) => e !== id));
    }
  };
  const handleDelete = () => {
    let updatedTodo = props.todos.filter((e) => !selectedItem.includes(e.id));
    updatedTodo.map((e, index) => ({ ...e, id: index }));
    props.deleteTodo(updatedTodo);
    setSelectedItem([]);
  };
  return (
    <div className="container">
      <form onSubmit={handleSubmit}>
        <input className="input" type="text" value={input} onChange={(e) => setInput(e.target.value)} />
        <button className="createbtn btn" type="submit">
          Create
        </button>
      </form>
      <div>
        <table className="todotable">
          <tbody>
            <tr>
              <th></th>
              <th>My Todos</th>
              <th>Status</th>
            </tr>
            {props.todos.map((e, index) => {
              return (
                <tr key={`${Date.now()} + ${index}`}>
                  <td>
                    <input type="checkbox" defaultChecked={selectedItem.includes(e.id)} onClick={() => handleCheckbox(e.id)} />
                  </td>
                  <td>
                    <Link to={{ pathname: `${e.title}`, state: { ...e } }}>{e.title}</Link>
                  </td>
                  <td>
                    <button className="statusbtn btn" onClick={() => handleUpdate(e.id)}>
                      {e.completed ? "Completed" : "uncomplete"}
                    </button>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
        <div className="deleteContainer">
          <button className="deletebtn btn" onClick={handleDelete}>
            Delete {selectedItem.length} items
          </button>
        </div>
      </div>
    </div>
  );
}

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

export default connect(mapStateToProps, { addTodo, updateTodo, deleteTodo })(App);
```

Good Luck for your future, Hope you have learned something new.🚀