Trabajo en una aplicación de tareas pendientes con React y las cosas se vuelven más claras, pero me cuesta entender el "ciclo de vida". En VueJS conozco un gancho ComponentDidMount() , que me ayudaría a resolver este problema si lo adivino, pero en React no puedo encontrarlo.
Tengo una matriz de todos como este: const todos = [{description: "walk dog", done: false}]
Este es el estado inicial de mi aplicación:
const [alltodos, handleTodos] = useState([]); Al cargar, uso este useEffect para obtener datos de localStorage.
useEffect(() => { const items = localStorage.getItem("todos"); const parsed = JSON.parse(items); handleTodos(parsed); }, []);Cuento mis todos con esta función:
const countTodos = () => { const donetodos = alltodos.filter((item) => { return !item.done; }); countOpen(donetodos.length); };Actualizo el recuento si cambia una dependencia:
useEffect(() => { countTodos(); localStorage.setItem("todos", JSON.stringify(alltodos)); }, [alltodos]);Entonces, lo que sucede es que el contador comienza con 0 y luego "parpadea" durante un milisegundo antes de mostrar la cantidad de todos que obtengo del almacenamiento local.
¿Hay alguna manera de prevenir ese comportamiento? Por lo que sé, el componente se procesa PRIMERO y luego se activa el gancho useEffect. ¿Cómo represento mi componente DESPUÉS de que los datos se extraigan del almacenamiento local?
La mejor manera de hacer esto sería con un estado inicial perezoso . Además, limpiar las variables y usar una [variable, setVariable] estandarizada le ahorrará dolores de cabeza en la depuración en el futuro.
const [alltodos, setAlltodos] = useState(() => { const items = localStorage.getItem("todos"); const parsed = JSON.parse(items); return parsed || ""; });Inicialice el estado allTodos con null . Siempre que este estado sea null , presente una notificación o simplemente devuelva null para no presentar nada.
Puede calcular el recuento de todos abiertos directamente desde el estado actual de alltodos , sin necesidad de useEffect .
const [alltodos, handleTodos] = useState(null); useEffect(() => { const items = localStorage.getItem("todos"); const parsed = items ? JSON.parse(items) : []; handleTodos(parsed); }, []); useEffect(() => { localStorage.setItem("todos", JSON.stringify(alltodos)); }, [alltodos]); if(alltodos === null) return 'Loading todos list'; // this is derived from state, so you don't have to create a state for it const openTodosCount = alltodos.reduce((acc, o) => acc + !o.done, 0);La forma más rápida sería agregar un nuevo estado que sería responsable de la carga. Por ejemplo
const [isLoading, setIsLoading] = useState(true); configúrelo inicialmente en verdadero y luego, después de hacer todos sus cálculos, cámbielo a false .
Luego, puede depender de ese estado y mostrar div con un texto "Loading" o cualquier otra cosa, pero cuando isLoading se vuelva false , mostrará los elementos del componente.