Tengo un sistema de carrito de compras en mi aplicación next.js usando Context.
Defino mi carrito con useState :
const [cartItems, setCartItems] = useState([]);
Luego uso useEffect para verificar y actualizar el almacenamiento local:
useEffect(() => { if (JSON.parse(localStorage.getItem("cartItems"))) { const storedCartItems = JSON.parse(localStorage.getItem("cartItems")); setCartItems([...cartItems, ...storedCartItems]); } }, []); useEffect(() => { window.localStorage.setItem("cartItems", JSON.stringify(cartItems)); }, [cartItems]); Esto almacena bien los elementos en localStorage, pero cuando actualizo, restablece el elemento cartItems en localStorage a una matriz vacía. He visto algunas respuestas en las que obtiene el elemento localStorage antes de configurar el estado del carrito, pero eso arroja errores de localStorage is not defined en Siguiente. ¿Cómo puedo hacer esto?
setCartItems establece el valor de cartItems para el siguiente procesamiento, por lo que en el procesamiento inicial es [] durante el segundo useEffect
Puede solucionar esto almacenando una referencia (que no se vuelve a renderizar en el cambio de estado) para saber si es el primer renderizado o no.
import React, { useState, useRef } from "react"; // ... // in component const initialRender = useRef(true); useEffect(() => { if (JSON.parse(localStorage.getItem("cartItems"))) { const storedCartItems = JSON.parse(localStorage.getItem("cartItems")); setCartItems([...cartItems, ...storedCartItems]); } }, []); useEffect(() => { if (initialRender.current) { initialRender.current = false; return; } window.localStorage.setItem("cartItems", JSON.stringify(cartItems)); }, [cartItems]);gracias a jamesmosier por su respuesta en gitHub
El problema que está viendo se debe a que localStorage (también conocido como window.localStorage) no está definido en el lado del servidor. El siguiente servidor representa sus componentes, por lo que cuando eso sucede e intenta acceder a localStorage, no puede encontrarlo. Tendrá que esperar hasta que el navegador lo muestre para poder usar localStorage.
enlace de respuesta completa aquí
EDITAR
puedes probar esto:
useEffect(() => { if (typeof window !== "undefined") { const storedCartItems = JSON.parse(localStorage.getItem("cartItems")); if(storedCartItems !== null) { setCartItems([...cartItems, ...storedCartItems]); } } }, []); useEffect(() => { if (typeof window !== "undefined") { window.localStorage.setItem("cartItems", JSON.stringify(cartItems)); } }, [cartItems]);React nunca actualiza el estado inmediatamente Es un proceso asincrónico, por ejemplo, si console.log(stateValue) justo después del método setState() obtendrá el valor prevState en un registro. Puedes leer más sobre esto aquí .
Eso está sucediendo exactamente aquí, ha llamado al método setState dentro del primer useEffect, el estado aún no se ha actualizado por reaccionar y estamos tratando de actualizar localStorage con el último valor de estado (por ahora es [] ya que react aún no ha actualizado el estado ). es por eso que el valor localStorage contiene una matriz vacía.
Para su caso, puede omitir la primera ejecución de 2nd useEffect como se menciona en su respuesta de @Samathingamajig.
PD: Gracias @Samathingamajig por señalar el error tonto, no sé cómo lo perdí. JAJAJA