Как работать с каждым отдельным отображаемым элементом, когда они отображаются из массива объектов в React?

#javascript #reactjs

#javascript #reactjs

Вопрос:

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

Родительский компонент:

 const Home = () => {
  const dummyData = [
    {
      id: 1,
      title: tshirt,
      price: 10
    },
    {
      id: 2,
      title: hat,
      price: 20
    }
  ]
  
  const [totalPrice, setTotalPrice] = useState(0);
  const itemNo = 2;
  
  const handleClick = (price) => {
     setTotalPrice(price * itemNo);
  }
  
  const RenderCards = () => {
    return (
      dummyData.map(
        (d) => 
          <Card key={d.id} title={d.title} price={d.price} totalPrice={totalPrice}/>
      )
    )
  }
  
  return(
    <>
      <RenderCards />
    </>
  )
}  

и дочерний компонент:

 const Card = (id, title, price, totalPrice) => {
  return (
    <>
      <div key={id}>
        <p>{title}</p>
        <p>{totalPrice}</p>
        <button onClick={() => handleClick(price)}>Click for total price</button>
      </div>
    </>
  )
}  

При нажатии кнопки на каждой карте я хотел бы отобразить общую цену для каждой карты, т. Е. Для карты 1 общая цена должна быть 10 * 2 = 20, а для карты 2 должна быть 40. Щелчок по карточке 1 должен изменять только {TotalPrice} карты 1, карта 2 не должна быть затронута, наоборот.

Однако то, что у меня есть до сих пор, при нажатии кнопки на обеих карточках будет отображаться одинаковая общая цена. Я понимаю это поведение, поскольку одни и те же данные передаются компоненту карты, но как я могу индивидуально установить данные для каждой карты в этом случае, когда компоненты отображаются из карты массива?

Комментарии:

1. Я не уверен, что следую логике того, что вы намереваетесь. Должно ли нажатие кнопки отображать новую «общую цену» для каждой карты или просто изменить цену, указанную на этой одной карте?

2. Вам нужен объект в вашем состоянии, подобный этому: { { id: 1, кол-во: 5}, { id: 2, кол-во: 10} }. В вашем setTotalPrice вам нужно передать существующее состояние и новое количество для этого продукта. На вашей карте общая цена = цена * кол-во. handleClick должен иметь идентификатор и количество (общее или добавить).

3. @RobinZigmond просто измените общую цену на каждой карте, скажем, нажав кнопку card 1, только card 1 {tootalPrice} должна измениться на 20. Карта 2 ничего не должна делать.

4. @JB_DELR можете ли вы предоставить подробный ответ, пожалуйста?

5. @thinkvantagedu, готово !

Ответ №1:

 const Home = () => {
  const dummyData = [
    {
      id: 1,
      title: tshirt,
      price: 10
    },
    {
      id: 2,
      title: hat,
      price: 20
    }
  ]
  
  const [totalPrice, setTotalPrice] = useState([]); //<-- an empty array for start

  
  const handleClick = (id, qty) => {
     let newState = [...totalPrice]; //<--- copy the state
     if (newState.find(item => item.id === id) != undefined) { // find the item to add qty, if not exists, add one
       newState.find(item => item.id === id).qty  = qty
     } else {
       newState.push({id:id, qty:qty});
     }
     setTotalPrice(newState); //<-- set the new state
  }
  
  const RenderCards = () => {
    return (
      dummyData.map(
            (d) => {
               const stateItem = totalPrice.find(item=> item.id === d.id); // return the item or undefined
               const qty = stateItem ? stateItem.qty : 0 // retreive qty from state by id or 0 if the product is not in the array
               return (
                 <Card key={d.id} title={d.title} price={d.price} totalPrice={d.price * qty}/>  //calculate the total    
               )
            }
      )
    )
  }
  
  return(
    <>
      <RenderCards />
    </>
  )
}
  

и карточка:

 const Card = (id, title, price, totalPrice) => {
  return (
    <>
      <div>
        <p>{title}</p>
        <p>{totalPrice}</p>
        <button onClick={() => handleClick(id, 1)}>Click for add one</button>  // add one, total price will be good on the next render
      </div>
    </>
  )
}
  

может быть, ошибка, но идея здесь

Комментарии:

1. Вы можете переименовать TotalPrice и setTotalPrice, например, в cartList и setCartList

2. Итак, ваше состояние выглядит следующим образом [ { id: 1, кол-во: 5}, { id: 2, кол-во: 10} ]

3. попробовал и выдал мне TypeError: Cannot read property 'qty' of undefined ошибку в строке const qty = totalPrice.find(item => item === d.id).qty

4. Массив пуст, поэтому нужно проверить, как в handleClick