I'm trying to set up an order list with react hooks. The method is correct but the components aren't updating until i force it from React dev tools. The button that add the order is in a component and the list is a different component.
I tried setting useEffect but the result is the same.
Here is the state declaration and the method
const [orderList, setOrderList] = React.useState([]);
const addToOrderList = (order) => {
const list = orderList;
if (list)
list.push(order);
setOrderList(list);
}
And here the components in the render
<div className="w-3/5">
<ItemDeliveryCard
fromMenu={true}
selectedMenu={selectedMenu}
orderList={orderList}
onClickHandler={(order) => addToOrderList(order)}
/>
</div>
<div >
<DeliveryCard orderListProp={orderList} />
</div>
The button in ItemDeliveryCard
<button
onClick={() => onClickHandler(product)}
className={gradients.redGradToL " w-80 flex flex-row items-center justify-center mb-5"}
>
<p className="uppercase">select this offer</p>
</button>
I tried the solutions from this post but useEffect doesn't seems to work
CodePudding user response:
You are mutating state where you need to treat it as immutable, try instead:
const addToOrderList = (order) => {
if (orderList) {
setOrderList(prevList => [...prevList, order]);
}
}
CodePudding user response:
The React hook way to modify a state:
const addToOrderList = (order) => {
setOrderList(list => (list ? list : []).concat(order));
}
A little explanation:
- Reason your code doesn't trigger update, is because the new value of list that you set,
setOrderList(newValue)
, is the same array reference as old value, React doesn't detect this mutation, thus no update. - It's recommended you use the updater function pattern:
setValue(oldValue => {
/* whatever mutation logic you need */
return newValue
})
Instead of moving the mutation logic outside then set the final value, like what you do currently. Reason is that this pattern would mitigate the stale closure problem.