{"id":8351,"date":"2025-07-27T21:32:32","date_gmt":"2025-07-27T21:32:31","guid":{"rendered":"https:\/\/namastedev.com\/blog\/?p=8351"},"modified":"2025-07-27T21:32:32","modified_gmt":"2025-07-27T21:32:31","slug":"build-a-todo-app-with-react-and-localstorage-9","status":"publish","type":"post","link":"https:\/\/namastedev.com\/blog\/build-a-todo-app-with-react-and-localstorage-9\/","title":{"rendered":"Build a Todo App with React and LocalStorage"},"content":{"rendered":"<h1>Build a Todo App with React and LocalStorage<\/h1>\n<p>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.<\/p>\n<h2>What You Will Learn<\/h2>\n<ul>\n<li>Setting up a React application.<\/li>\n<li>Creating components for the Todo app.<\/li>\n<li>Using LocalStorage to store data.<\/li>\n<li>Implementing basic CRUD operations.<\/li>\n<\/ul>\n<h2>Getting Started with React<\/h2>\n<p>Before diving into the code, ensure you have Node.js installed on your machine. If you haven\u2019t installed React yet, you can quickly set up a React application using Create React App.<\/p>\n<pre><code>npx create-react-app todo-app<\/code><\/pre>\n<p>Change your directory to your new app:<\/p>\n<pre><code>cd todo-app<\/code><\/pre>\n<p>Once inside the project, you can open it in your favorite code editor.<\/p>\n<h2>Creating the Todo App Structure<\/h2>\n<p>First, we need to create the following components:<\/p>\n<ul>\n<li><strong>TodoList<\/strong>: Displays the list of tasks.<\/li>\n<li><strong>TodoItem<\/strong>: Represents a single task.<\/li>\n<li><strong>AddTodo<\/strong>: A form to add a new task.<\/li>\n<\/ul>\n<h3>TodoList Component<\/h3>\n<p>Let&#8217;s start with the <strong>TodoList<\/strong> component. Create a new file named <strong>TodoList.js<\/strong> inside the <strong>src<\/strong> directory.<\/p>\n<pre><code>import React from 'react';\nimport TodoItem from '.\/TodoItem';\n\nconst TodoList = ({ todos, deleteTodo }) =&gt; {\n    return (\n        &lt;div&gt;\n            &lt;h2&gt;Todo List&lt;\/h2&gt;\n            &lt;ul&gt;\n                {todos.map((todo, index) =&gt; (\n                    &lt;TodoItem key={index} todo={todo} deleteTodo={deleteTodo} \/&gt;\n                ))}\n            &lt;\/ul&gt;\n        &lt;\/div&gt;\n    );\n};\n\nexport default TodoList;<\/code><\/pre>\n<h3>TodoItem Component<\/h3>\n<p>Create a new file named <strong>TodoItem.js<\/strong> in the same directory:<\/p>\n<pre><code>import React from 'react';\n\nconst TodoItem = ({ todo, deleteTodo }) =&gt; {\n    return (\n        &lt;li&gt;\n            {todo}\n            &lt;button onClick={deleteTodo} &gt;Delete&lt;\/button&gt;\n        &lt;\/li&gt;\n    );\n};\n\nexport default TodoItem;<\/code><\/pre>\n<h3>AddTodo Component<\/h3>\n<p>Next, create the <strong>AddTodo<\/strong> component in <strong>AddTodo.js<\/strong>:<\/p>\n<pre><code>import React, { useState } from 'react';\n\nconst AddTodo = ({ addTodo }) =&gt; {\n    const [value, setValue] = useState('');\n\n    const handleSubmit = (e) =&gt; {\n        e.preventDefault();\n        if (!value) return;\n        addTodo(value);\n        setValue('');\n    };\n\n    return (\n        &lt;form onSubmit={handleSubmit}&gt;\n            &lt;input \n                type=\"text\" \n                value={value} \n                onChange={(e) =&gt; setValue(e.target.value)} \n                placeholder=\"Add a new task\" \n            \/&gt;\n            &lt;button type=\"submit\"&gt;Add&lt;\/button&gt;\n        &lt;\/form&gt;\n    );\n};\n\nexport default AddTodo;<\/code><\/pre>\n<h2>Setting Up the App Component<\/h2>\n<p>Now let&#8217;s set up the main application component in <strong>App.js<\/strong> where we\u2019ll manage state and connect everything together.<\/p>\n<pre><code>import React, { useState, useEffect } from 'react';\nimport TodoList from '.\/TodoList';\nimport AddTodo from '.\/AddTodo';\n\nconst App = () =&gt; {\n    const [todos, setTodos] = useState([]);\n\n    useEffect(() =&gt; {\n        const storedTodos = JSON.parse(localStorage.getItem('todos'));\n        if (storedTodos) {\n            setTodos(storedTodos);\n        }\n    }, []);\n\n    useEffect(() =&gt; {\n        localStorage.setItem('todos', JSON.stringify(todos));\n    }, [todos]);\n\n    const addTodo = (newTodo) =&gt; {\n        setTodos([...todos, newTodo]);\n    };\n\n    const deleteTodo = (index) =&gt; {\n        const newTodos = todos.filter((_, i) =&gt; i !== index);\n        setTodos(newTodos);\n    };\n\n    return (\n        &lt;div&gt;\n            &lt;h1&gt;Todo App&lt;\/h1&gt;\n            &lt;AddTodo addTodo={addTodo} \/&gt;\n            &lt;TodoList todos={todos} deleteTodo={deleteTodo} \/&gt;\n        &lt;\/div&gt;\n    );\n};\n\nexport default App;<\/code><\/pre>\n<h2>Understanding LocalStorage<\/h2>\n<p>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:<\/p>\n<pre><code>window.localStorage<\/code><\/pre>\n<p>In our app, we will use LocalStorage to save the list of todos whenever they are updated using the effect hook:<\/p>\n<h3>Using Logic for Data Persistence<\/h3>\n<p>Within the <strong>useEffect<\/strong>, the first effect runs to fetch todos from LocalStorage when the component mounts, while the second effect persists any changes to the todos:<\/p>\n<pre><code>useEffect(() =&gt; {\n    const storedTodos = JSON.parse(localStorage.getItem('todos'));\n    if (storedTodos) {\n        setTodos(storedTodos);\n    }\n}, []);\n\nuseEffect(() =&gt; {\n    localStorage.setItem('todos', JSON.stringify(todos));\n}, [todos]);<\/code><\/pre>\n<h2>Styling the Todo App<\/h2>\n<p>You can enhance your app&#8217;s appearance by adding some basic styles. Create a new <strong>styles.css<\/strong> file in the <strong>src<\/strong> directory and add the following styles:<\/p>\n<pre><code>body {\n    font-family: Arial, sans-serif;\n}\n\nh1, h2 {\n    color: #333;\n}\n\nul {\n    list-style: none;\n    padding: 0;\n}\n\nbutton {\n    margin-left: 10px;\n    padding: 5px 10px;\n    background-color: #28a745;\n    color: white;\n    border: none;\n    cursor: pointer;\n    border-radius: 5px;\n}\n\nbutton:hover {\n    background-color: #218838;\n}\n\nform {\n    margin-bottom: 20px;\n}<\/code><\/pre>\n<h2>Conclusion<\/h2>\n<p>Congratulations! You have built a fully functional Todo application with React and LocalStorage. You&#8217;ve learned how to create components, manage state, and store data locally, all essential skills for any developer.<\/p>\n<p>This Todo app is a great foundation, and you can expand its functionality by adding features like:<\/p>\n<ul>\n<li>Task editing capabilities.<\/li>\n<li>Marking tasks as complete.<\/li>\n<li>Implementing due dates.<\/li>\n<\/ul>\n<h2>Further Resources<\/h2>\n<p>To deepen your understanding of React and LocalStorage, consider the following resources:<\/p>\n<ul>\n<li><a href=\"https:\/\/reactjs.org\/docs\/getting-started.html\">React Official Documentation<\/a><\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Window\/localStorage\">MDN Web Docs on LocalStorage<\/a><\/li>\n<li><a href=\"https:\/\/css-tricks.com\/using-localstorage-react\/\">Using LocalStorage in React by CSS-Tricks<\/a><\/li>\n<\/ul>\n<p>Happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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<\/p>\n","protected":false},"author":92,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[398],"tags":[224],"class_list":["post-8351","post","type-post","status-publish","format-standard","category-react","tag-react"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/8351","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/users\/92"}],"replies":[{"embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/comments?post=8351"}],"version-history":[{"count":1,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/8351\/revisions"}],"predecessor-version":[{"id":8352,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/posts\/8351\/revisions\/8352"}],"wp:attachment":[{"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/media?parent=8351"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/categories?post=8351"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/namastedev.com\/blog\/wp-json\/wp\/v2\/tags?post=8351"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}