anonymous
anonymous

Reputation: 369

Set State in a loop React Native

I have some props in the form of an array of objects that I am using to update my "items" state. I am able to loop through the objects and build objects containing the "product_id" and the "quantity". When I just console.log I can see the correct data, however when I try to update the state I get the error "Too many re-renders, react limits the number of renders to prevent an infinite-loop."

 const [items, setItems] = useState(
    {
      product_id: 93,
      quantity: 2,
    },
    {
      product_id: 22,
      variation_id: 23,
      quantity: 1,
    },
  );
  const cart = props.cart;
  Object.keys(cart).forEach(function (key) {
    const prod = {
      product_id: cart[key].id,
      quantity: cart[key].quantity,
    };
    setItems((currentItems) => {
      return {prod, ...currentItems};
    });
  });

Edit My cart props is pulled from redux using the following code

function mapStateToProps(state) {
  return {
    cart: state.cart,
  };
}
export default connect(mapStateToProps)(Checkout);

The problem is that this prop has more attributes than just the quantity and id that I need.

Upvotes: 1

Views: 3066

Answers (2)

brijesh-pant
brijesh-pant

Reputation: 1145

You don't need to set the state again and again in a loop. Rather, just loop on the array, get the items and finally set the state

   const [items, setItems] = React.useState(
    {
      product_id: 93,
      quantity: 2
    },
    {
      product_id: 22,
      variation_id: 23,
      quantity: 1
    }
  );

  const { cart } = props;
  useEffect(() => {
    const products = Object.entries(cart).map(([key, { id, quantity }]) => ({
      product_id: id,
      quantity: quantity
    }));
    setItems(currentItems => ({ ...products, ...currentItems }));
  }, [cart]);

Upvotes: 3

Kavian Rabbani
Kavian Rabbani

Reputation: 984

You should use an array or an object as the state. you are passing two separate objects to useState, wrap them in an object with proper keys. or use an array.

it seems you have forgotten to add a wrap your initial object inside curly braces.  

const [items, setItems] = useState([
  {
    product_id: 93,
    quantity: 2,
  },
  {
    product_id: 22,
    variation_id: 23,
    quantity: 1,
  },
]);  

then

return [prod, ...currentItems];  

as a suggestion:
it's better to make new objects and set them in the state all at once.

const objectsToAdd = Object.values(cart).map(function (cartItem) {
  return {
    product_id: cartItem.id,
    quantity: cartItem.quantity,
  };
});

setItems((currentItems) => {
  return [...objectsToAdd, ...currentItems];
})

Upvotes: 2

Related Questions