У меня есть некоторые реквизиты в виде массива объектов, которые я использую для обновления моего состояния «элементы». Я могу перебирать объекты и создавать объекты, содержащие «product_id» и «количество». Когда я просто вижу console.log, я вижу правильные данные, однако при попытке обновить состояние я получаю сообщение об ошибке "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};
    });
  });

Изменить реквизиты моей корзины вытащил из редукса, используя следующий код

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

Проблема в том, что у этой опоры больше атрибутов, чем просто количество и идентификатор, которые мне нужны.

1
anonymous 28 Июл 2020 в 17:27

2 ответа

Лучший ответ

Вам не нужно устанавливать состояние снова и снова в цикле. Скорее просто зациклите массив, получите элементы и, наконец, установите состояние

   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]);
1
brijesh-pant 28 Июл 2020 в 15:20

Вы должны использовать массив или объект в качестве состояния. вы передаете два отдельных объекта в useState, оборачивая их в объект с соответствующими ключами. или использовать массив.

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,
  },
]);  

Тогда

return [prod, ...currentItems];  

Как предложение:
Лучше создавать новые объекты и устанавливать их в состояние сразу.

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

setItems((currentItems) => {
  return [...objectsToAdd, ...currentItems];
})
1
Kavian Rabbani 28 Июл 2020 в 14:45