(sory for my english)
Hi, this code working half to half. I can delete product but i must go to another page , and back , to rerender. i dont know why ?
Code: Parent Component:
function ShoppingCard() {
const shoppingCard = useContext<any>(ShoppingCardContext);
const [shoppingCard2, setShoppingCard2] = useState<any>(shoppingCard);
useEffect(() => {
setShoppingCard2(shoppingCard);
}, [shoppingCard, shoppingCard2]);
const removeProduct = (shopCart: any) => {
let index = shoppingCard.findIndex(
(oneProduct: any) => oneProduct.idProduct === shopCart.idProduct
);
shoppingCard.splice(index, 1);
setShoppingCard2(shoppingCard);
};
// passes this function to the next component through the next component.
Parent component 1
child component 2
child Component 3
And i use this fuction in a button to remove element. In console i see that shoppingCard and shoppingCard2 is update but only in child 3. And to see the efect (rerender) i must go to another page and back. In app i use React-Router.
Ps. This is my first post
CodePudding user response:
Issue
You are mutating the state when deleting from the shoppingCard2
array, and then never creating a new array reference for React so reconciliation works. In other words, React doesn't "see" that the shoppingCard2
array is a new array so it doesn't trigger a rerender. You see the mutation when navigating away and back to the page.
const removeProduct = (shopCart: any) => {
let index = shoppingCard.findIndex(
(oneProduct: any) => oneProduct.idProduct === shopCart.idProduct
);
shoppingCard.splice(index, 1); // <-- mutation!!
setShoppingCard2(shoppingCard); // <-- same array reference
};
Solution
Shallow copy the shoppingCard2
array and remove the element. Use Array.prototype.filter
to accomplish this.
Example:
const removeProduct = (shopCart: any) => {
setShoppingCard2(shoppingCard => shoppingCard.filter(
(oneProduct: any) => oneProduct.idProduct !== shopCart.idProduct
));
};
Suggestion
An improvement would be to expose a state updater function from the ShoppingCardContext
so it can maintain the state invariant instead of offloading this to consumers. There's really no reason to "duplicate" the shopping card state locally if it can be helped.
CodePudding user response:
The best will be to use a global state. You can read more about
- React Context
- Redux
- another state manager