Search code examples
javascriptreactjssetstate

Trying to manipulate state array in React


I need to write two functions, one for updating the shopping cart with new products (reserves) and another one to remove products from the cart. I have many product suppliers, so I want to divide my "cart" array into sections like this:

{
  "supplier1": ["product0": {props}, "product1": {props}, "productN": {props}],
  "supplier2": ["product0": {props}, "product1": {props}, "productN": {props}],
  "supplierN": ["product0": {props}, "product1": {props}, "productN": {props}],
}

I can succesfully add suppliers to my state array and also pushing product to supplier's arrays.
When i use

setCart(cart)

cart array is updating but this is still old array, so React won't rerender my component

And in this case

setCart([...cart])

cart array just becomes empty
So here is code of adding new products

const [cart, setCart] = useState([])
const addToCart = useCallback((options) => {
  //options.cart_section and options.reserve
  if(typeof cart[options.cart_section] === 'undefined'){
    cart[options.cart_section] = []
  }
  cart[options.cart_section].push(options.reserve)
  setCart([...cart])
}, [])

and code of removing products form cart

const removeFromCart = useCallback((options) => {
  let index = cart[options.cart_section].indexOf(options.reserve) - 1
  cart[options.cart_section].splice(index,1)
  setCart([...cart])
})

It removes specified product but React doesn't rerender the component (same as in function below)
Sorry for my English and thanks for the help


Solution

    • Fist point. You can not assign key value like you did to array. but you can push objects as items of array. each object considered as a unique supplier. So your array should be like this:
    [
      {
        supplierName: 'supplie name 1',
        products: [
         {name: 'product name 1'}, 
         {name: 'product name 2'}
        ]
      },
      {
        supplierName: 'supplie name 2',
        products: [
         {name: 'product name 1'}, 
        {name: 'product name 2'}]
      }
    ]
    
    • Second point. never mutate state itself. you are mutating cart by pushing some thing inside of it. This way react will not rerender your component as you are not updating your state via setState. you have to create a variable in your function from your state this way:
      let tempCart = cart.map(object => ({...object}))
    

    after that you can push new supplier or product and at the end you should update your state via setCart. this way:

      setCart(tempCart)
    

    this way you are updating your state via setState and react will treat this action as (need DOM to update) then your component will get rerender