Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

193
Views
LocalStorage doesn't set items into itself

I've got a bug with LocalStorage on react.js. I try to set a todo into it, but it doesn't load. This is the code:

import React, { useState, useRef, useEffect } from 'react';
import './App.css';
import TodoList from './TodoList';
const { v4: uuidv4 } = require('uuid');
const LOCAL_STORAGE_KEY = 'todoApp.todos'
function App() {
  const [todos, setTodos] = useState([]);
  const TodoNameRef = useRef()

  useEffect(() => {
    const storedTodos = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY))
    if (storedTodos) setTodos(storedTodos)
  }, [])
  useEffect(() => {
      localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(todos))
  }, [todos])
  function HandleAddTodo(e){
    const name = TodoNameRef.current.value
    if (name==='') return
    setTodos(prevTodos => {
      return[...prevTodos, { id:uuidv4(), name:name, complete:false}]
    })
    TodoNameRef.current.value = null
  }

  return (
    <>
      <TodoList todos={todos}/>
      <input ref={TodoNameRef} type="text" />
      <button onClick={HandleAddTodo}>Add todo</button>
      <button>clear todo</button>
      <p>0 left todo</p>
    </>
  )
}

export default App;
This is TodoList.js

import React from 'react'
import Todo from './Todo';
export default function TodoList({ todos }) {
  return (
    todos.map(todo =>{
        return <Todo key ={todo.id} todo={todo} />
    })
    
  )
}
And as last Todo.js:

import React from 'react'

export default function Todo({ todo }) {
  return (
    <div>
        <label>
            <input type="checkbox" checked={todo.complete}/>
            {todo.name}
        </label>
        
    </div>
  )
}

What the code has to do is load a todo into the local storage, and after refreshing the page reload it into the document. The code I implemented I just started with react but I hope anyone can pass me the right code to make it work. If anyone need extra explenation, say it to me.

Kind regards, anonymous

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

You added the getItem and setItem methods of localStorage in two useEffect hooks. The following code intializes the todo value in localStorage when reloading the page.

  useEffect(() => {
      localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(todos))
  }, [todos])

So you need to set the todo value in HandleAddTodo event.

I edited your code and look forward it will help you.

import React, { useState, useRef, useEffect } from 'react';
import './App.css';
import TodoList from './TodoList';
const { v4: uuidv4 } = require('uuid');
const LOCAL_STORAGE_KEY = 'todoApp.todos'
function App() {
  const [todos, setTodos] = useState([]);
  const TodoNameRef = useRef()

  useEffect(() => {
    const storageItem = localStorage.getItem(LOCAL_STORAGE_KEY);
    const storedTodos = storageItem ? JSON.parse(storageItem) : [];
    if (storedTodos) setTodos(storedTodos)
  }, []);

  function HandleAddTodo(e){
    const name = TodoNameRef.current.value;
    if (name==='') return;
    const nextTodos = [...todos, { id:uuidv4(), name:name, complete:false}];
    setTodos(nextTodos);
    localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(todos));
    TodoNameRef.current.value = null
  }

  return (
    <>
      <TodoList todos={todos}/>
      <input ref={TodoNameRef} type="text" />
      <button onClick={HandleAddTodo}>Add todo</button>
      <button>clear todo</button>
      <p>0 left todo</p>
    </>
  )
}

export default App;
about 4 years ago · Juan Pablo Isaza Report

0

Try to decouple your local storage logic into it's own react hook. That way you can handle getting and setting the state and updating the local storage along the way, and more importantly, reuse it over multiple components.

The example below is way to implement this with a custom hook.

const useLocalStorage = (storageKey, defaultValue = null) => {
  const [storage, setStorage] = useState(() => {
    const storedData = localStorage.getItem(storageKey);
    if (storedData === null) {
      return defaultValue;
    }

    try {
      const parsedStoredData = JSON.parse(storedData);
      return parsedStoredData;
    } catch(error) {
      console.error(error);
      return defaultValue;
    }
  });

  useEffect(() => {
    localStorage.setItem(storageKey, JSON.stringify(storage));
  }, [storage]);

  return [storage, setStorage];
};

export default useLocalStorage;

And you'll use it just like how you would use a useState hook. (Under the surface it is not really more than a state with some side effects.)

const LOCAL_STORAGE_KEY = 'todoApp.todos'

function App() {
   const [todos, setTodos] = useLocalStorage(LOCAL_STORAGE_KEY, []);

   const handleAddTodo = event => {
    setTodos(prevTodos => {
      return[...prevTodos, { 
        id: uuidv4(), 
        name, 
        complete: false
      }]
    })
  };

  return (
    <button onClick={HandleAddTodo}>Add todo</button>
  );
}
about 4 years ago · Juan Pablo Isaza Report

0

There is no need of adding the second useEffect. You can set your local Storage while submitting in the handleTodo function. Things you need to add or remove :

  1. Remove the Second useEffect.

  2. Modify your handleTodo function :

     const nextTodos = [...todos, { id:uuidv4(), name:name,complete:false}];
     setTodos(nextTodos);
     localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(nextTodos));
    

Note: Make sure you won't pass todos instead of nextTodos as we know setTodos is an async function There might be a chance we are setting a previous copy of todos

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!