Soy nuevo en React y no puedo entender qué está mal con mi uso del gancho useEffect . El código se compila con éxito y todo parece funcionar. Los componentes agregados por el usuario se muestran en el navegador y se agregan a localStorage , pero al actualizar, solo se muestra el componente de ejemplo (Cuadro 1) y la entrada realizada por el usuario se pierde. ¿Alguna idea sobre cuál podría ser el problema?
mport React, { Fragment, useState, useRef, useEffect } from 'react'; import { v4 as uuidv4} from 'uuid'; import { BoxList } from './components/BoxList'; import { SearchBox } from './components/SearchBox'; const KEY = "boxApp.boxes"; export function App() { const [boxes, setBoxes] = useState([ {id: 1, title: 'Box 1', content: 'This is just an example of a box, remove it and create yours!' } ]) const boxTitleRef = useRef(); const boxContentRef = useRef(); useEffect(() => { const storedBoxes = JSON.parse(localStorage.getItem(KEY)); if (storedBoxes) { setBoxes(storedBoxes); } }, []); useEffect(() =>{ localStorage.setItem(KEY, JSON.stringify(boxes)); }, [boxes]); const removeBox = (id) => { const remainingBoxes = boxes.filter((box) => box.id !== id); setBoxes(remainingBoxes); } const addNewBox = (evt) => { evt.preventDefault(); const boxTitle = boxTitleRef.current.value; const boxContent = boxContentRef.current.value; if (boxTitle === '' || boxContent === '') return; setBoxes( previousBoxes => { return ([...previousBoxes, { id: uuidv4(), title: boxTitle, content: boxContent}]) }); boxTitleRef.current.value = null; boxContentRef.current.value = null; } return ( <Fragment> <SearchBox /> <div> <h2>Add a box</h2> <form> <input type='text' placeholder='Title' ref={boxTitleRef}></input> <input type='text' placeholder='Content' ref={boxContentRef}></input> <button type='submit' onClick={addNewBox}>➕</button> </form> </div> <BoxList boxes={boxes} removeBox={removeBox}/> </Fragment> ); } export default App;El problema proviene del siguiente useEffect que tiene:
useEffect(() =>{ localStorage.setItem(KEY, JSON.stringify(boxes)); }, [boxes]); Actualiza localStorage cada vez que cambia boxes , pero también cuando el componente se monta por primera vez, y en este punto boxes es igual al estado inicial dado a useState . Puede eliminarlo y actualizar localStorage al agregar y eliminar elementos:
const addNewBox = (evt) => { evt.preventDefault(); const boxTitle = boxTitleRef.current.value; const boxContent = boxContentRef.current.value; if (boxTitle === "" || boxContent === "") return; const newBoxes = [...boxes, { id: uuidv4(), title: boxTitle, content: boxContent }]; setBoxes(newBoxes); localStorage.setItem(KEY, JSON.stringify(newBoxes)); boxTitleRef.current.value = null; boxContentRef.current.value = null; }; const removeBox = (id) => { const remainingBoxes = boxes.filter((box) => box.id !== id); localStorage.setItem(KEY, JSON.stringify(remainingBoxes)); setBoxes(remainingBoxes); }; También puede cambiar su llamada useState a esto:
const [boxes, setBoxes] = useState(JSON.parse(localStorage.getItem(KEY)) || [ {id: 1, title: 'Box 1', content: 'This is just an example of a box, remove it and create yours!' } ]); Y elimine el siguiente useEffect que tiene:
useEffect(() => { const storedBoxes = JSON.parse(localStorage.getItem(KEY)); if (storedBoxes) { setBoxes(storedBoxes); } }, []);Debería resolver su problema si establece su valor de estado inicial condicionalmente desde el almacenamiento local como este.
Aquí está la pieza que necesita actualizar
const initialValue = JSON.parse(localStorage.getItem(KEY)); const [boxes, setBoxes] = useState(initialValue ? initialValue : [ {id: 1, title: 'Box 1', content: 'This is just an example of a box, remove it and create yours!' } ])