Srikanth Technologies

Todos Application in React using LocalStorage

In this blog, we develop a React Application that allows users to create, list and delete Todos. Application uses LocalStorage of browser to store todos so that user can come back anytime and can access todos.

Concepts Used

The following concepts are used in this application.

Source Code - Todos.js

Here is the source code for Todos.js, which contains the following components:

import React, { useEffect, useState } from 'react'

export default function Todos() {
    let [todos, setTodos] = useState([]);

    useEffect(() => {
        // get data for key todos from localStorage 
        let todoItems = window.localStorage.getItem("todos")
        if (todoItems) {
            setTodos(JSON.parse(todoItems))
        }
    }, [])


    function getNextId() {
        // find out id for last item and add 1 to it 
        if (todos.length === 0)
            return 1;
        return todos[todos.length - 1].id + 1
    }

    function addTodo(todoText) {
        let nextId = getNextId()
        let newTodos = [...todos, { id: nextId, text: todoText }]
        updateLocalStorage(newTodos) 
        setTodos(newTodos)
    }

    function deleteTodo(id) {
        let newTodos = todos.filter((todo) => todo.id !== id)
        setTodos(newTodos)
        updateLocalStorage(newTodos)
    }

    function updateLocalStorage(todos) {
        window.localStorage.setItem("todos", JSON.stringify(todos))
    }

    return (
        <>
            <h1>Todos</h1>
            <AddTodo addTodo={addTodo} />
            <p></p>
            <ListTodos todos={todos} todoDone={deleteTodo} />
        </>
    )
}

function AddTodo({addTodo}) {
    let [todoText, setTodoText] = useState("")

    function addNewTodo(e) {
        e.preventDefault();
        addTodo(todoText)
        setTodoText("")
    }

    return (
        <form onSubmit={addNewTodo}>
            Todo : <input type="text" value={todoText} required
                       onChange={(e) => setTodoText(e.target.value)} />
            <input type="submit" value="Add" />
        </form>
    )
}

function ListTodos({ todos, todoDone }) {
    return (
        <ul>
            {todos.map((todo) => <li key={todo.id}>{todo.text}
                <button className="btn btn-link" onClick={() => todoDone(todo.id)}>Done</button></li>)}
        </ul>
    )
}   

Important Snippets

Here are important snippets from the source code:

Source Code - index.js

The following is the code in index.js to import and render Todos component.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Todos from './Todos';

ReactDOM.render(, document.getElementById('root'));

React 18

The above code is to be modified as follows, if you are using React 18.

import React from 'react';
import ReactDOM from 'react-dom/client';
import Todos from './Todos';
import './index.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render();

Source Code - index.html

We need to include bootstrap related entries in index.html as follows:

<!DOCTYPE html>
<html lang="en">
  <head>
     <title>React App</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
      integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div class="container" id="root"></div>
  </body>
</html>

Sample Run

When you run this application first time, no todos are displayed as we haven't entered any. But after adding some todos, we get them listed with delete button.

As todos are stored in LocalStorage, we can retrieve them anytime as they are stored in Browser persistently.

Here is the page when application first loaded.

Here is page after you added some todos. Clicking on Done button will delete todo.

Keep Learning, Keep Growing

Srikanth Pragada