Home > Net >  How update state in parent component from child, child component?
How update state in parent component from child, child component?

Time:07-07

(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
  • Related