Building a TODO List App in React.js with Local Storage.
Published: 2024-05-11 06:37:15


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xrwrfu9ptcvtkvjmp4jd.png)
React.js is a popular JavaScript library for building user interfaces, and it’s a great choice for creating web applications like a TODO list. In this blog, we will walk you through the process of building a TODO list app using React.js, with the added functionality of local storage to persist your tasks even after you close the browser.

**Prerequisites**
Before we get started, make sure you have the following prerequisites:

Node.js and npm installed on your computer.
Building a TODO List App in React.js with Local Storage
React.js is a popular JavaScript library for building user interfaces, and it’s a great choice for creating web applications like a TODO list. In this blog, we will walk you through the process of building a TODO list app using React.js, with the added functionality of local storage to persist your tasks even after you close the browser.Prerequisites

Before we get started, make sure you have the following prerequisites:

Node.js installed on your computer.

**Step 1: Create a New React App**
We will start by creating a new React app using Vite which is a popular tool for setting up a new React project with a predefined folder structure.

Open your terminal and run the following commands:

```
npm create vite@latest todo-app
cd todo-app
npm i
```
This will create a new directory named todo-app and set up a basic React project structure inside it.

**Step 2: Building the TODO List**
Now, let’s dive into the development of our TODO list app. We’ll create a simple interface with an input field to add tasks and a list to display them.

**2.1. Todo.jsx**
Open the src/components/Todo.jsx file and replace its contents with the following code:

```
import { useEffect, useState } from "react";
import "./Todo.css"; 
import TodoItem from "./TodoItem";
```

```
const Todo = () => {
  const [task, setTask] = useState([]);
  const [todo, setTodo] = useState("");

  useEffect(() => {
    const stored = JSON.parse(localStorage.getItem("todo"));
    if (stored) {
      setTask(stored);
    }
  }, []);

  const updateLocalStorage = (updatedTasks) => {
    localStorage.setItem("todo", JSON.stringify(updatedTasks));
    setTask(updatedTasks);
  };

  const addTodo = () => {
    if (todo.trim() !== "") {
      const newTask = { id: Date.now(), task: todo, completed: false };
      const updatedTasks = [...task, newTask];
      updateLocalStorage(updatedTasks);
      setTodo("");
    }
  };

  const deleteTodo = (id) => {
    const updatedTasks = task.filter((item) => item.id !== id);
    updateLocalStorage(updatedTasks);
  };

  const toggleTodo = (id) => {
    const updatedTasks = task.map((item) =>
      item.id === id ? { ...item, completed: !item.completed } : item
    );
    updateLocalStorage(updatedTasks);
  };

  return (
    <div className="todo-container">
      <h1>Todo</h1>
      <div className="add-todo">
        <input
          type="text"
          className="input-todo"
          value={todo}
          onChange={(e) => setTodo(e.target.value)}
        />
        <button className="todo-btn" onClick={addTodo}>
          Add Todo
        </button>
      </div>
      <div className="todo-list">
        <h1>Todo List</h1>
        <ul>
          {task.map((item) => (
            <TodoItem
              key={item.id}
              item={item}
              onDelete={deleteTodo}
              onToggle={toggleTodo}
            />
          ))}
        </ul>
      </div>
    </div>
  );
};

export default Todo;
```
This code sets up the main structure of your TODO app. We’re using React hooks to manage the state of the TODOs and to interact with local storage.

**2.1.2 Todo.css**
To make the app look good, we need some basic styling. Create a file named Todo.css in the src directory and add the following CSS:

```
.todo-container {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
  background-color: #f9f9f9;
  border-radius: 8px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.add-todo {
  margin-bottom: 20px;
}

.input-todo {
  padding: 10px;
  width: 70%;
  border: 1px solid #ccc;
  border-radius: 4px;
}

.todo-btn {
  padding: 10px 20px;
  border: none;
  background-color: #007bff;
  color: #fff;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.todo-btn:hover {
  background-color: #0056b3;
}

.todo-list {
  list-style-type: none;
  padding: 0;
}

.todo-item {
  display: flex;
  align-items: center;
  margin-bottom: 10px;
}

.todo-item p {
  margin: 0;
  flex-grow: 1;
  padding-left: 10px;
}

.completed {
  text-decoration: line-through;
  color: #888;
}

.delete-btn {
  margin-left: 10px;
  background-color: #dc3545;
  color: #fff;
  border: none;
  border-radius: 4px;
  padding: 5px 10px;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.delete-btn:hover {
  background-color: #c82333;
}
```
**2.2. TodoItem.jsx**
Open the src/components/TodoItem.jsx file and replace its contents with the following code:

```
mport PropTypes from "prop-types";
import "./TodoItem.css";
const TodoItem = ({ item, onDelete, onToggle }) => {
  return (
    <li className="todo-item">
      {" "}
      <input
        type="checkbox"
        checked={item.completed}
        onChange={() => onToggle(item.id)}
      />
      <p className={item.completed ? "completed" : ""}>{item.task}</p>
      <button className="todo-btn" onClick={() => onDelete(item.id)}>
        Delete Todo
      </button>
    </li>
  );
};

TodoItem.propTypes = {
  item: PropTypes.shape({
    id: PropTypes.number.isRequired,
    task: PropTypes.string.isRequired,
    completed: PropTypes.bool.isRequired,
  }).isRequired,
  onDelete: PropTypes.func.isRequired,
  onToggle: PropTypes.func.isRequired,
};

export default TodoItem;
```
**2.2.1 TodoItem.css**
To make the app look good, we need some basic styling. Create a file named TodoItem.css in the src directory and add the following CSS:

```
.todo-item {
  display: flex;
  align-items: center;
  padding: 10px;
  border-bottom: 1px solid #ccc;
}

.todo-item p {
  margin: 0;
  padding-left: 10px;
  flex-grow: 1;
}

.completed {
  text-decoration: line-through;
  color: #888;
}

.todo-btn {
  padding: 5px 10px;
  background-color: #dc3545;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.todo-btn:hover {
  background-color: #c82333;
}
```
**2.3. App.Jsx**
Import the your todo component here to get the final result , here how you can do that:

```
import "./App.css";
import Todo from "./components/Todo";
function App() {
  return (
    <>
      <Todo />
    </>
  );
}
```
**2.3.1 App.css**
Import the some css here to align div at center for your root, here how you can do that:

```
#root {
  max-width: 1280px;
  margin: 0 auto;
  padding: 2rem;
  text-align: center;
}
```
**Step 3: Running the App**
Now that you’ve created your TODO app, you can run it by executing the following command in the terminal:

```
npm run dev
```
This will start your React app, and you can access it in your web browser at http://localhost:5173.

**Step 4: Using the TODO App**
Your TODO app allows you to add tasks by typing in the input field and clicking the “Add Todo” button. Once you’ve added a task, it will appear in the list below. To remove a task, simply click the “Delete Todo” button next to it. What makes this app special is that it also uses local storage to persist your tasks. Even if you close the browser and reopen it, your tasks will still be there.

**Conclusion**
Congratulations! You’ve successfully built a TODO list app in React.js with local storage. This app provides a user-friendly interface for managing your tasks and ensures that your tasks are saved and loaded from local storage, making it a practical and efficient tool for your daily productivity needs.