проблема с ключевым параметром в ReactJS хуков, обновление всех элементов товаров при использовании (добавление / вычитание) по отдельности - PullRequest
0 голосов
/ 13 июля 2020

Меня немного смущает применение ключевого параметра к приведенному ниже коду в ReactJS, я понимаю, что нам нужно использовать ключевой параметр, чтобы однозначно идентифицировать каждый элемент DOM, когда я пытался использовать key = {index} в кнопках возникает ошибка (обнаружены двое детей с одним и тем же ключом).

Я также немного озадачен, поскольку обновление setQuantity обновляет все элементы во всех продуктах (как показано на скриншоте ниже), не уверен, как я могу использовать уникальный ключевой элемент только для обновления каждого количества продукта.

Любая помощь приветствуется.

Обновление 1: код теперь обновляется с ключом = {productName}, но значение добавления / вычитания обновляется для всех продуктов при добавлении / вычитании одного продукта

function Home({ props }) {
  //quantitiyselected, to set the no. of items purchased
  const [quantitiyselected, setQuantity] = useState(0);

  // below function to add, subtract quantity
  let selectquantity = (e) => {
    if (e.currentTarget.name == "add") {
      let i = quantitiyselected + 1;
      setQuantity(i);
    } else if (e.currentTarget.name == "subtract" && quantitiyselected > 0) {
      let z = quantitiyselected - 1;
      setQuantity(z);
    } else;
  };

  return (
    <div className="products">
      {props.map((eachproduct, index) => {
        let productName = eachproduct.product_name;
        let producNumber = eachproduct.producNumber;
        let price = eachproduct.price;
        let desc = eachproduct.productDescription;
        let photo = eachproduct.image_URL;
        let stockQuantity = eachproduct.stockQuantity;
        return (
          <div className="products" key={productName }>
            <ul>
              <li>
                <img className="products-image" src={photo} />
              </li>
              <li>{productName} </li>
              <li>
                Item No:{producNumber}(InStock:{stockQuantity})
              </li>
              <li>price:{price}£ </li>
              <li>{desc}</li>
              <li>
                <ButtonGroup aria-label="quantityofproduct">
                  <Button
                    
                    variant="secondary"
                    name="subtract"
                    value="subtract"
                    onClick={selectquantity}
                  >
                    -
                  </Button>
                  <Button variant="secondary">
                    {quantitiyselected}
                  </Button>
                  <Button
                    
                    variant="secondary"
                    name="add"
                    value="add"
                    onClick={selectquantity}
                  >
                    +
                  </Button>
                </ButtonGroup>
                &nbsp;
                 variant="primary">
                  Buy
                </Button>
              </li>
            </ul>
          </div>
        );
      })}
    </div>
  );
}

export default Home;

введите описание изображения здесь

1 Ответ

1 голос
/ 13 июля 2020

Вы применяете key={index} к нескольким элементам в вашем рендере (<div>, <ul> и каждый <Button />), но ему нужно только go на элементе верхнего уровня, который визуализируется в массиве. который в вашем случае является <div className="products">.

В стороне, индекс массива обычно не является хорошим кандидатом на ключ - он должен быть уникальным для каждого элемента, который отображается . В вашем примере я думаю, что producNumber будет лучшим выбором, поскольку я предполагаю, что это некий уникальный идентификатор для каждого продукта.

  • удалите key={index} из всего, что у вас есть
  • добавьте key={producNumber} к внутреннему <div className="products">

Этот является хорошим ресурсом, чтобы узнать больше о React's key prop.

Причина, по которой у всех продуктов одинаковое количество, заключается в том, что у вас есть только один номер для вашего штата:

React.useState(0);

Вы пытаетесь отслеживать количество для каждого продукта, поэтому вам нужно количество для каждого продукта . Один из способов сделать это - использовать объект ({}), который имеет свойства вашего producNum и количество в качестве их значения. Например:

const products = [
  { name: "thing", num: 152 },
  { name: "other-thing", num: 254 },
];

const initialQuantities = products.reduce(
  (quantities, product) => ({ ...quantities, [product.num]: 0 }),
  {}
);

console.log(initialQuantities);

Это создает объект с каждым продуктом с начальным количеством 0.

Когда вы затем увеличиваете или уменьшаете количество, вы передаете номер продукта продукта, который вы нажали на функцию, а затем вы можете установить новое количество только этого продукта, оставив другие количества продукта нетронутыми, используя Синтаксис распространения (...) :

const initialQuantities = products.reduce(
  (quantities, product) => ({ ...quantities, [product.producNumber]: 0 }),
  {}
);

const [quantities, setQuantities] = React.useState(initialQuantities);

const increase = (productNum) => {
  setQuantities({
    ...quantities,
    [productNum]: quantities[productNum] + 1,
  });
};

const decrease = (productNum) => {
  setQuantities({
    ...quantities,
    [productNum]: Math.max(0, quantities[productNum] - 1),
  });
};

, а затем ваш onClick станет:

onClick={() => increase(producNumber)}

и

onClick={() => decrease(producNumber)}

Простую реализацию можно увидеть здесь: https://codesandbox.io/s/icy-dust-nbetq?file= / src / App . js: 175-655

...