React useState clarification needed. setState of a cart

Viewed 39

Hi I got cat to work but need clarification on this or maybe even better way of doing things in the future.

So I have my cart

{
products: array(),
total_price: int()
}

cart is stored in cartContext and in localStorage.

Then I have all kind of methods to manipulate but there is one thing I don't get.

Delete from cart First method of creating new cart w/o clicked item

export const deleteFromCart = (existingCart, productDatabaseId) => {
  let newProducts = existingCart.products.filter((obj) => {
    return obj.databaseId !== productDatabaseId;
  });
  existingCart.products = newProducts;
  existingCart = calculateTotalPrice(existingCart);
  localStorage.setItem("cart", JSON.stringify(existingCart));

  return existingCart;
};

Then handler

  const [cart, setCart] = useContext(CartContext);
  const handleDeleteFromCart = (databaseId) => {
    let existingCart = localStorage.getItem("cart");
    if (process.browser) {
      existingCart = JSON.parse(existingCart);
      let updatedCart = deleteFromCart(existingCart, databaseId);

      setCart(updatedCart);
    }
  };

Questions:

  1. As you can see I'm creating whole new cart everytime when doing changes. I think it's clean solution as long as CartProvider is stateless with hooks. Am I right?
  2. I'm getting exisistingCart from local storage but I tried to use just state object for that manner
  const [cart, setCart] = useContext(CartContext);
  const handleDeleteFromCart = (databaseId) => {

    if (process.browser) {
      let existingCart = cart;
      let updatedCart = deleteFromCart(existingCart, databaseId);

      setCart(updatedCart);
    }
  };

In this case state won't refresh. setCart is setting previous version of the cart or not setting it at all. State doesn't change, only local storage cart is changing so after refresh (hook on loading cart from local storage) cart is proper(w/o clicked item) but it's not realtime. Why? My guess is that deleteFromCart method takes to loong to execute and setCart is executed before hand?

Need some clariffication on this.

1 Answers

My guess is that deleteFromCart method takes to loong to execute and setCart is executed before hand?

No this is not the case.

The useState will bail out of the render (aka. you do not see the changes until the next render and if there is no next render, as in your case, the old data is still shown), if the previous and current value in the state are the same, shallowly (current === next).

So if the cart that you put into the state is the same as previously, you do not see the change.

And that is what you are doing. existingCart is cart and you mutate this. Afterwards, you are setting the state to cart again, so the previous and current objects are the same, but mutated and react will skip the render.

The first code works, because you are creating a new object from the local state every time, so the current !== next.

What you need to do is to create a new cart object that you change: let existingCart = {...cart};

So in short, never mutate your state, but instead create a new object to safe the changes to.

Related