Build a Todo App with React and LocalStorage
Building a simple Todo app is a rite of passage for many web developers, and it serves as an excellent way to understand the core concepts of React. In this guide, we will walk through the process of creating a Todo app that not only uses React but also leverages LocalStorage to persist our data. This approach ensures that even if the user refreshes the page, their tasks remain intact.
What You Will Learn
- Setting up a React application.
- Creating components for the Todo app.
- Using LocalStorage to store data.
- Implementing basic CRUD operations.
Getting Started with React
Before diving into the code, ensure you have Node.js installed on your machine. If you haven’t installed React yet, you can quickly set up a React application using Create React App.
npx create-react-app todo-app
Change your directory to your new app:
cd todo-app
Once inside the project, you can open it in your favorite code editor.
Creating the Todo App Structure
First, we need to create the following components:
- TodoList: Displays the list of tasks.
- TodoItem: Represents a single task.
- AddTodo: A form to add a new task.
TodoList Component
Let’s start with the TodoList component. Create a new file named TodoList.js inside the src directory.
import React from 'react';
import TodoItem from './TodoItem';
const TodoList = ({ todos, deleteTodo }) => {
return (
<div>
<h2>Todo List</h2>
<ul>
{todos.map((todo, index) => (
<TodoItem key={index} todo={todo} deleteTodo={deleteTodo} />
))}
</ul>
</div>
);
};
export default TodoList;
TodoItem Component
Create a new file named TodoItem.js in the same directory:
import React from 'react';
const TodoItem = ({ todo, deleteTodo }) => {
return (
<li>
{todo}
<button onClick={deleteTodo} >Delete</button>
</li>
);
};
export default TodoItem;
AddTodo Component
Next, create the AddTodo component in AddTodo.js:
import React, { useState } from 'react';
const AddTodo = ({ addTodo }) => {
const [value, setValue] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (!value) return;
addTodo(value);
setValue('');
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Add a new task"
/>
<button type="submit">Add</button>
</form>
);
};
export default AddTodo;
Setting Up the App Component
Now let’s set up the main application component in App.js where we’ll manage state and connect everything together.
import React, { useState, useEffect } from 'react';
import TodoList from './TodoList';
import AddTodo from './AddTodo';
const App = () => {
const [todos, setTodos] = useState([]);
useEffect(() => {
const storedTodos = JSON.parse(localStorage.getItem('todos'));
if (storedTodos) {
setTodos(storedTodos);
}
}, []);
useEffect(() => {
localStorage.setItem('todos', JSON.stringify(todos));
}, [todos]);
const addTodo = (newTodo) => {
setTodos([...todos, newTodo]);
};
const deleteTodo = (index) => {
const newTodos = todos.filter((_, i) => i !== index);
setTodos(newTodos);
};
return (
<div>
<h1>Todo App</h1>
<AddTodo addTodo={addTodo} />
<TodoList todos={todos} deleteTodo={deleteTodo} />
</div>
);
};
export default App;
Understanding LocalStorage
LocalStorage is a web storage solution that allows us to store key-value pairs in a web browser with no expiration time. The data stored in LocalStorage is accessible through the window object:
window.localStorage
In our app, we will use LocalStorage to save the list of todos whenever they are updated using the effect hook:
Using Logic for Data Persistence
Within the useEffect, the first effect runs to fetch todos from LocalStorage when the component mounts, while the second effect persists any changes to the todos:
useEffect(() => {
const storedTodos = JSON.parse(localStorage.getItem('todos'));
if (storedTodos) {
setTodos(storedTodos);
}
}, []);
useEffect(() => {
localStorage.setItem('todos', JSON.stringify(todos));
}, [todos]);
Styling the Todo App
You can enhance your app’s appearance by adding some basic styles. Create a new styles.css file in the src directory and add the following styles:
body {
font-family: Arial, sans-serif;
}
h1, h2 {
color: #333;
}
ul {
list-style: none;
padding: 0;
}
button {
margin-left: 10px;
padding: 5px 10px;
background-color: #28a745;
color: white;
border: none;
cursor: pointer;
border-radius: 5px;
}
button:hover {
background-color: #218838;
}
form {
margin-bottom: 20px;
}
Conclusion
Congratulations! You have built a fully functional Todo application with React and LocalStorage. You’ve learned how to create components, manage state, and store data locally, all essential skills for any developer.
This Todo app is a great foundation, and you can expand its functionality by adding features like:
- Task editing capabilities.
- Marking tasks as complete.
- Implementing due dates.
Further Resources
To deepen your understanding of React and LocalStorage, consider the following resources:
Happy coding!
