Tengo un error con LocalStorage en react.js. Trato de configurar un todo en él, pero no se carga. Este es el código:
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; import React from 'react' import Todo from './Todo'; export default function TodoList({ todos }) { return ( todos.map(todo =>{ return <Todo key ={todo.id} todo={todo} /> }) ) } import React from 'react' export default function Todo({ todo }) { return ( <div> <label> <input type="checkbox" checked={todo.complete}/> {todo.name} </label> </div> ) }Lo que tiene que hacer el código es cargar una tarea pendiente en el almacenamiento local y, después de actualizar la página, volver a cargarla en el documento. El código que implementé lo comencé con reaccionar, pero espero que alguien pueda pasarme el código correcto para que funcione. Si alguien necesita una explicación extra, que me lo diga.
Saludos cordiales, anonimo
Agregó los métodos getItem y setItem de localStorage en dos ganchos useEffect. El siguiente código inicializa el valor de todo en localStorage al recargar la página.
useEffect(() => { localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(todos)) }, [todos])Por lo tanto, debe establecer el valor de todo en el evento HandleAddTodo.
Edité tu código y espero que te ayude.
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;Intente desacoplar su lógica de almacenamiento local en su propio gancho de reacción. De esa manera, puede manejar obtener y configurar el estado y actualizar el almacenamiento local en el camino y, lo que es más importante, reutilizarlo en múltiples componentes.
El siguiente ejemplo es una forma de implementar esto con un gancho personalizado.
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; Y lo usará de la misma manera que usaría un useState . (Debajo de la superficie, en realidad no es más que un estado con algunos efectos secundarios).
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> ); }No hay necesidad de agregar el segundo useEffect . Puede configurar su local Storage mientras realiza el envío en la función handleTodo . Cosas que necesita agregar o eliminar:
Elimina el segundo useEffect .
Modifique su función handleTodo:
const nextTodos = [...todos, { id:uuidv4(), name:name,complete:false}]; setTodos(nextTodos); localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(nextTodos)); Nota: asegúrese de no pasar todos en lugar de nextTodos , ya que sabemos que setTodos es una función asíncrona. Es posible que estemos configurando una copia anterior de todos .