The object I want to edit gets edited in JSON format, but only previous data gets displayed in the browser. I use these hooks to get a list of products from local storage
const Cart = () => { const [products, setProducts] = useState([]); const [loading, setLoading] = useState(true); useEffect(()=>{ setProducts(loadCart()); setLoading(false) },[])
Then I map all of the objects
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> )
incrementAmount()
function looks like that:
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) }
From what I see in the console, the array looks fine and the object I wanted to edit got edited. FE: I had an object {name:”hoodie”, amount:3} after clicking “+” button it changes properly to {name:”hoodie”, amount:4} (in both products
and tempList
) but in console only, in the document it still displays product.amount
as 3 and I have no idea why
Advertisement
Answer
Instead of pass an object to setState
you can pass a function and when you have an object into the state that you want to keep old values you must use a function.
Because state
may be updated asynchronously, you should not rely on their values for calculating the next state.
You must change the incrementAmount()
function like this:
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; }); }