A continuación se muestra mi código para el proyecto de ejemplo de reacción:
import Products from "./components/Products"; import Cart from "./components/Cart"; import { useState } from "react"; import './App.css'; function App() { const [page, setPage] = useState("Products"); const [cart, setCart] = useState([]) const switchPages = (nextPage)=> { setPage(nextPage) } const addCart =(p) =>{ console.log("{...p}", {...p}); console.log("p", p); setCart([...cart, {...p}]) } const removeCart = (p)=> { console.log(p); setCart(cart.filter(i => i !== p)) } return ( <div className="App"> <button onClick={() => switchPages("Products")}>View Products</button> <button onClick={() => switchPages("Cart")}>View Cart {cart.length}</button> {page === "Products" && <Products addCart={addCart}/>} {page === "Cart" && <Cart cartItems={cart} removeCart={removeCart}/>} </div> ); } export default App;A continuación se muestra el código para Products.js
import React, { useState } from 'react' const Products = ({addCart}) => { const [products] = useState([ { name: "iPhone", price: 80000 }, { name: "Laptop", price: 55500 }, { name: "iPad", price: 45000 } ]) return ( <div> { products.map((product, idx) => { return ( <div className="box" key={idx}> <h1 className="small">{product.name}</h1> <p>Price: {product.price}</p> <button onClick={()=> addCart(product)}>Add to cart</button> </div> ) }) } </div> ) } export default Products Como puede ver, mientras configuro el carrito en la función addCart, estoy usando {...p} setCart([...cart, {...p}]) , en lugar de solo p setCart([...cart, p]) . Si uso solo p, elimina todos los elementos si intento eliminar uno solo y si uso {..p}, elimina la entrada única. ¿Alguien puede explicar por qué tenemos que usar {...p} en lugar de solo p?
Gracias
La diferencia entre p y {...p} es que este último copia el objeto. Parece que estás mezclando referencias en alguna parte, pero no en el fragmento que compartiste.
ahora con su código podemos decir dónde está el problema, básicamente está pasando objetos por referencia y usando esa referencia para eliminar un objeto, así que básicamente cuando pasa solo p terminará con una matriz como esta
[ obj1, obj2, obj3, ... objN, ]digamos que hizo clic muchas veces en el objeto (llamémoslo génesis):
{ name: "iPhone", price: 80000 },Básicamente, parece que todos los objetos son iguales en diferentes partes de la memoria, pero lo que sucede es que todos los obj1, obj2, obj3 ... etc. apuntan al objeto génesis, por lo tanto, cuando intenta usar el filtro con esta condición:
cart.filter(i => i !== p) está comprobando obj1 === genesis , obj2 === genesis , ... , objN === genesis que sabemos que son todos iguales:
es por eso que su filtro está eliminando todos sus objetos
Pasando a la parte { ...p } , si entiendes el concepto anterior, ahora sabes que usar el operador de propagación copiará tu objeto, por lo tanto, al hacer el filtro, eliminará el correcto.
nota: sería mucho mejor filtrar usando algún tipo de identificación para que pueda controlar el filtrado aún mejor, también prefiero agregar los artículos al carrito de la siguiente manera:
<button onClick={()=> addCart({...product})}>Add to cart</button> usando el operador de propagación aquí, por lo que puede usar solo p directamente en los otros métodos.