El objeto que quiero editar se edita en formato JSON, pero solo se muestran los datos anteriores en el navegador. Uso estos ganchos para obtener una lista de productos del almacenamiento local
const Cart = () => { const [products, setProducts] = useState([]); const [loading, setLoading] = useState(true); useEffect(()=>{ setProducts(loadCart()); setLoading(false) },[])Luego mapeo todos los objetos.
const mapProducts = (products) => { return ( <> {products.map((product) => { return ( <> <div className="cart-detail"> <h4>{product.name} - {product.price}$ / total: {product.price * product.amount}$</h4> <h4>{product.amount}</h4> <button onClick={() => incrementAmount(product)}>+</button> </div> </> ) })} </> ) } return ( <Base title="Cart"> {loading && <h1>Loading...</h1>} {!loading && mapProducts(products)} </Base> ) La función incrementAmount() se ve así:
const incrementAmount = (product) => { let tempList = products for (let i = 0; i < tempList.length; i++) { if (tempList[i].id === product.id) { tempList[i].amount++; } } setProducts(tempList) } Por lo que veo en la consola, la matriz se ve bien y se editó el objeto que quería editar. FE: Tenía un objeto {nombre:"sudadera con capucha", cantidad:3} después de hacer clic en el botón "+", cambia correctamente a {nombre:"sudadera con capucha", cantidad:4} (tanto en products como en tempList ), pero solo en la consola, en el documento todavía muestra product.amount como 3 y no tengo idea de por qué
En lugar de pasar un objeto a setState , puede pasar una función y cuando tiene un objeto en el estado en el que desea mantener los valores antiguos, debe usar una función.
Debido a que state puede actualizarse de forma asíncrona, no debe confiar en sus valores para calcular el siguiente estado.
Debe cambiar la función incrementAmount() de esta manera:
const incrementAmount = (product) => { setProducts(prevState => { const newState = [...prevState]; for (let i = 0; i < newState.length; i++) { if (newState[i].id === product.id) { newState[i].amount++; } } return newState; }); }Esto se debe a que react activa una nueva representación solo cuando cambia el estado. Cuando llama a setProducts en incrementAmount , esencialmente está pasando el mismo objeto (con una propiedad anidada actualizada). Así que reaccionar no registra esto como un cambio de estado. Esto se debe a cómo funcionan los objetos y las matrices en Javascript. Para que su código funcione, cambie let tempList = products por let tempList = [...products] . Esto creará un nuevo objeto en la memoria y copiará los valores de los products . Y finalmente, cuando pasa esto a setProducts , se activará una nueva representación actualizando su HTML.