如何使用钩子更新状态对象中的特定值?

问题描述

我正在尝试更新购物篮中某件商品的数量,但很难让它正常工作?

我有一个输入字段,让用户更新数量数量用于根据数量更新商品的总价格,以及总购物篮成本。

我已经设法在组成篮子的对象数组中获得了正确的项目,但是我似乎无法使用状态挂钩更新数量,我该如何做到这一点?

我的想法是在 if 语句中更新它,然后用更新后的数量用新对象替换旧对象......但我不知道如何做到这一点......

这是我目前所拥有的....

    const [basketData,setBasketData] = useState(null);

    useEffect(() => {
        setBasketData(basket);
    },[]);

    const quantityHandler = (e) => {
        basketData.forEach((basket) => {
            if (Object.values(basket).includes(e.target.name)) {
            }
        });
    };

这是用于篮子的数据:

export const basket = [
    {
        productID: 1,productName: "Mountain Dew",isAgeRestricted: false,productDescription: "Carbonated citrus flavoured soft drink",unitPrice: 1.8,quantity: 2,},{
        productID: 2,productName: "Desperados",isAgeRestricted: true,productDescription: "Beer with flavourings and Tequila",unitPrice: 2.6,quantity: 6,{
        productID: 3,productName: "Jack Daniels",productDescription:
            "A perfect mix of Jack Daniel's Old No. 7 Tennessee Whiskey & cola",unitPrice: 3.35,quantity: 4,];

解决方法

你使用quantityHandler onClick 吗?像这样:

const quantityHandler = (e) => {
  let newDataArray = basketData.map((basket) => {
      if (basket.includes(e.target.name)) {
         return {...basket,quantity: e.target.value}
      }
      return basket;
  });
  setBasketData([...newDataArray])
};

当你做更复杂的事情时,你使用 map 而不是 forEach。并返回:{...basket,quantity: value} 将返回该对象上的数组 + 更新的数量。如果它不包含正确的名称,它只会返回该项目。 然后将旧数组设置为更新的数组。

你也可以使用 if(basket.name === e.target.name) 来代替包含,它看起来更准确:)

,

这是一个完整的解决方案(也可在 https://stackblitz.com/edit/react-basket55?file=src/App.js 获得):

import React,{ useState,useEffect } from "react";
import "./style.css";

export default function App() {
  const basket = [
    {
      productID: 1,productName: "Dew",quantity: 1
    },{
      productID: 2,productName: "Bud",{
      productID: 3,productName: "Jack",quantity: 1
    }
  ];

  const [basketData,setBasketData] = useState(basket);

  function handleInputChange(e) {
    let newDataArray = basketData.map(basketItem => {
      if (basketItem.productName == e.target.form.itemName.value) {
        let x = e.target.form.itemQuantity.value
          ? e.target.form.itemQuantity.value
          : 1;
        basketItem.quantity = x;
      }
      return basketItem;
    });
    setBasketData([...newDataArray]);
    
  }

  return (
    <div>
      <h1>Basket Example</h1>
      <form>
        <label>
          Item:
          <select name="itemName" onChange={handleInputChange}>
            {basket.map(function(data,index) {
              return (
                <option key={index} value={data.productName}>
                  {data.productName}
                </option>
              );
            })}
          </select>
        </label>
        <br />
        <label>
          Item Quantity:
          <input
            name="itemQuantity"
            type="Number"
            onChange={handleInputChange}
          />
        </label>
      </form>
      {basketData.map(i => {
        return (
          <p key={i.productName} >
            Item: {i.productName} {i.quantity}
          </p>
        );
      })}
    </div>
  );
}