Building a Simple Todo App with React and Local Storage

Building a Simple Todo App with React and Local Storage

React is a popular JavaScript library for building user interfaces, and it's an excellent choice for creating small to large-scale applications. In this tutorial, we'll create a simple Todo app using React and store the tasks using the browser's Local Storage, allowing us to maintain the tasks even after refreshing the page.


To follow along with this tutorial, you should have a basic understanding of:

  • HTML, CSS, and JavaScript
  • React fundamentals (components, state, and props)

Getting Started

First, let's set up our React project using the Create React App (CRA) tool. Open your terminal and run the following command:

  1. npx create-react-app react-todo-app

This command will create a new React project called «react-todo-app.» After the installation is complete, navigate to the project folder and start the development server:

  1. cd react-todo-app
  2. npm start

Now, open your browser and go to "http://localhost:3000" to see your new React app.

Building the Todo App

Next, let's start building our Todo app. We'll create two main components: «TodoForm» for adding new tasks and «TodoList» for displaying the tasks.

Creating the TodoForm Component

First, create a new file called «TodoForm.js» in the «src» folder and add the following code:

  1. import React, { useState } from 'react';
  3. const TodoForm = ({ addTask }) => {
  4. const [input, setInput] = useState('');
  6. const handleSubmit = (e) => {
  7. e.preventDefault();
  8. if (input.trim()) {
  9. addTask(input);
  10. setInput('');
  11. }
  12. };
  14. return (
  15. <form onSubmit={handleSubmit}>
  16. <input
  17. type="text"
  18. value={input}
  19. onChange={(e) => setInput(}
  20. placeholder="Add a task"
  21. />
  22. <button type="submit">Add</button>
  23. </form>
  24. );
  25. };
  27. export default TodoForm;

In the «TodoForm» component, we're using the «useState» hook to manage the input state. When the user submits the form, we call the «handleSubmit» function, which checks if the input is not empty, adds the task using the «addTask» function received via props, and then resets the input field.

Creating the TodoList Component

Now, let's create the «TodoList» component. Create a new file called «TodoList.js» in the «src» folder and add the following code:

  1. import React from 'react';
  3. const TodoList = ({ tasks, deleteTask }) => {
  4. return (
  5. <ul>
  6. {, index) => (
  7. <li key={index}>
  8. {task}
  9. <button onClick={() => deleteTask(index)}>Delete</button>
  10. </li>
  11. ))}
  12. </ul>
  13. );
  14. };
  16. export default TodoList;

The «TodoList» component receives the tasks array and the «deleteTask» function via props. It maps over the tasks array and displays each task along with a delete button. When the user clicks the delete button, it calls the «deleteTask» function with the task's index.

Updating the App Component

Now, let's update our «App.js» file to include the «TodoForm» and «TodoList» components:

  1. import React, { useState, useEffect } from 'react';
  2. import TodoForm from './TodoForm';
  3. import TodoList from './TodoList';
  4. import './App.css';
  6. const App = () => {
  7. const [tasks, setTasks] = useState([]);
  9. useEffect(() => {
  10. const storedTasks = JSON.parse(localStorage.getItem('tasks'));
  11. if (storedTasks) {
  12. setTasks(storedTasks);
  13. }
  14. }, []);
  16. useEffect(() => {
  17. localStorage.setItem('tasks', JSON.stringify(tasks));
  18. }, [tasks]);
  20. const addTask = (task) => {
  21. setTasks([...tasks, task]);
  22. };
  24. const deleteTask = (index) => {
  25. const newTasks = [...tasks];
  26. newTasks.splice(index, 1);
  27. setTasks(newTasks);
  28. };
  30. return (
  31. <div className="App">
  32. <h1>Todo App</h1>
  33. <TodoForm addTask={addTask} />
  34. <TodoList tasks={tasks} deleteTask={deleteTask} />
  35. </div>
  36. );
  37. };
  39. export default App;

In the «App» component, we're using the «useState» hook to manage the tasks array. We're also using the «useEffect» hook to load the tasks from Local Storage when the component mounts and update Local Storage whenever the tasks array changes.

The «addTask» function adds a new task to the tasks array, while the «deleteTask» function removes a task based on its index.

Finally, we render the «TodoForm» and «TodoList» components, passing the necessary functions and data as props.

Testing the Todo App

Now that our Todo app is complete, you can test it by adding and deleting tasks. The tasks will be stored in your browser's Local Storage, so they will persist even after you refresh the page.


In this tutorial, we've built a simple Todo app using React and Local Storage. This example demonstrates how to create a basic React app with a form and a list, as well as how to use the browser's Local Storage for data persistence.

This Todo app can be further improved by adding features like task editing, task prioritization, or filtering tasks by their completion status. You can also explore using a more sophisticated state management solution, like Redux, or connect your app to a backend service for data persistence across devices.

We use cookies to improve your browsing experience. By continuing to use this website, you consent to our use of cookies. Learn More