如何在 REACT JS 中为 onChange 事件更新 JSON 对象的状态?

How to Update JSON Object's state for onChange event in REACT JS?

我有 myrecords[] 的状态,其中包含 JSON 对象,格式如下:

{
    "records": {
        "Master Automotives": [
            {
                "SparePartID": "43",
                "Name": "Oil and Lubricants",
                "Price": "4500",
                "VendorID": "48",
                "CompanyName": "Master Automotives",
                 "Qty": 1,
                 "TotalPrice": "4500"

            },
            {
                "SparePartID": "45",
                "Name": "Lights",
                "Price": "2300",
                "VendorID": "48",
                "CompanyName": "Master Automotives",
                 "Qty": 1,
                 "TotalPrice": "2300"
            }
        ],
        "Repair Solutions": [
            {
                "SparePartID": "47",
                "Name": "Steering Wheel",
                "Price": "1500",
                "VendorID": "60",
                "CompanyName": "Repair Solutions",
                 "Qty": 1,
                 "TotalPrice": "1500"
            }
        ],
        
         "FiveStar Automotives": [
            {
                "SparePartID": "51",
                "Name": "Brakes",
                "Price": "234",
                "VendorID": "70",
                "CompanyName": "FiveStar Automotives",
                 "Qty": 1,
                 "TotalPrice": "234"
            },
            {
                "SparePartID": "53",
                "Name": "Clutch",
                "Price": "999",
                "VendorID": "70",
                "CompanyName": "FiveStar Automotives",
                 "Qty": 1,
                 "TotalPrice": "999"
            },
              {
                "SparePartID": "55",
                "Name": "LED",
                "Price": "288",
                "VendorID": "70",
                "CompanyName": "FiveStar Automotives",
                 "Qty": 1,
                 "TotalPrice": "288"
            }
        ]
    }
}

现在我在 React js 中显示此记录的方式是所有项目都显示在行中并按其 CompanyNames 分组,并且每个项目都有一个输入字段用于数量。 默认数量为 1,因此总价与单价相同。

现在我想要 Qty 的任何特定输入字段的 onChange,JSON 中相应的 TotalPrice 项目 Object 也应该在 myrecords[] 状态下更新。 Qty 也应该在 myrecords[].

的状态下更新

P.S:myrecords[] 包含 JSON object 不是数组。

这是我的 用于显示 JSON 对象记录的反应代码:

  
  {Object.keys(this.state.myrecords).map((CompanyName, i) => (
<div key={CompanyName}>
   <h2>Supplier: {CompanyName}</h2>
   
  {this.state.myrecords[CompanyName].map((product, i) => (
  <tr>

    <td>
      <h4> {product["SparePartID"]} </h4>
    </td>

    <td>
      <h4>{product["Name"]} </h4>
    </td>

    <td>
      <h4> {product["Price"]} </h4>
    </td>

    <td>
      <input type="number"
      value={product["Qty"]}
      min="1"
      onChange={(e) => this.onChangeQty(product["SparePartID"], e)}/>
    </td>

    <td> $ {product["TotalPrice"]}
    </td>

  </tr>
  ))}
  
  </div>

  ))}

onChangeQty函数如下**(这是我需要帮助的地方)**:

onChangeQty(sid,e)
{
   const items = this.state.myrecords;
  const item = items.find(item => item.SparePartID === sid);
  item.Qty = e.target.value;
  item.TotalPrice = item.Qty * item.Price;

  this.setState({
     myrecords: items
   });
}

先改这个

{this.state.myrecords[CompanyName].map((product, i) => (

{this.state.myrecords[CompanyName].map((product, j) => (

因为我们已经在上面的地图中使用了 i

然后改变这个

onChange={(e) => this.onChangeQty(product["SparePartID"], e)}

onChange={(e) => this.onChangeQty(CompanyName, j, e)}

然后你的 onChange 应该是

onChangeQty(CompanyName,j,e)
{
   const items = {...this.state.myrecords};
  items[CompanyName][j].Qty = e.target.value;
  items[CompanyName][j].TotalPrice = e.target.value * items[CompanyName][j].Price;

  this.setState({
     myrecords: items
   });
}

如果您不喜欢基于Change 的索引,您也可以像下面那样(基于sid)。只需将 CompanyName,sid,e) 传递给此函数 onChange={(e) => this.onChangeQty:

onChangeQty(CompanyName,sid,e)
{
   const items = {...this.state.myrecords};
  const j = items[CompanyName].findIndex(item => item.SparePartID === sid);
  items[CompanyName][j].Qty = e.target.value;
  items[CompanyName][j].TotalPrice = e.target.value * items[CompanyName][j].Price;

  this.setState({
     myrecords: items
   });
}

警告:代码未经测试。请检查并告诉我:)

您正试图在 this.state.myrecord 中查找项目。但是你应该在特定的公司。这是 DEMO.

import React from "react";
import ReactDOM from "react-dom";

const RECORDS = {
  "Master Automotives": [
    {
      SparePartID: "43",
      Name: "Oil and Lubricants",
      Price: "4500",
      VendorID: "48",
      CompanyName: "Master Automotives",
      Qty: 1,
      TotalPrice: "4500"
    },
    {
      SparePartID: "45",
      Name: "Lights",
      Price: "2300",
      VendorID: "48",
      CompanyName: "Master Automotives",
      Qty: 1,
      TotalPrice: "2300"
    }
  ],
  "Repair Solutions": [
    {
      SparePartID: "47",
      Name: "Steering Wheel",
      Price: "1500",
      VendorID: "60",
      CompanyName: "Repair Solutions",
      Qty: 1,
      TotalPrice: "1500"
    }
  ],

  "FiveStar Automotives": [
    {
      SparePartID: "51",
      Name: "Brakes",
      Price: "234",
      VendorID: "70",
      CompanyName: "FiveStar Automotives",
      Qty: 1,
      TotalPrice: "234"
    },
    {
      SparePartID: "53",
      Name: "Clutch",
      Price: "999",
      VendorID: "70",
      CompanyName: "FiveStar Automotives",
      Qty: 1,
      TotalPrice: "999"
    },
    {
      SparePartID: "55",
      Name: "LED",
      Price: "288",
      VendorID: "70",
      CompanyName: "FiveStar Automotives",
      Qty: 1,
      TotalPrice: "288"
    }
  ]
};

class App extends React.Component {
  state = {
    records: RECORDS
  };

  onChangeQty = (companyName, sid, e) => {
    const { records } = this.state;

    const newQty = e.target.value;

    this.setState({
      records: {
        ...records,
        [companyName]: records[companyName].map(product =>
          product.SparePartID === sid
            ? {
                ...product,
                Qty: newQty,
                TotalPrice: newQty * product.Price
              }
            : product
        )
      }
    });
  };

  render() {
    const { records } = this.state;

    return (
      <div className="App">
        {Object.keys(records).map((CompanyName, i) => (
          <div key={CompanyName}>
            <h2>Supplier: {CompanyName}</h2>
            {records[CompanyName].map((product, i) => (
              <tr>
                <td>
                  <h4> {product["SparePartID"]} </h4>
                </td>

                <td>
                  <h4>{product["Name"]} </h4>
                </td>

                <td>
                  <h4> {product["Price"]} </h4>
                </td>

                <td>
                  <input
                    type="number"
                    value={product["Qty"]}
                    min="1"
                    onChange={e =>
                      this.onChangeQty(CompanyName, product["SparePartID"], e)
                    }
                  />
                </td>

                <td> $ {product["TotalPrice"]}</td>
              </tr>
            ))}
          </div>
        ))}
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

问题是 this.state.myrecords 是一个对象,因此我们不能直接在其上使用 find。您还需要使用 updater function (check doc for more details).

您的问题的解决方案是:在 onChange 函数中也传递 companyName,然后 运行 仅循环特定公司详细信息数组。传递公司名称将帮助您轻松更新状态,否则您需要 运行 在所有数组上循环。

像这样:

onChange={(e) => this.onChangeQty(product["SparePartID"], CompanyName, e)}

onChangeQty(sid, companyName, e) {
  const value = e.target.value;
  this.setState(prevState => {

    return {
      myrecords: {
        ...prevState.myrecords,
        [companyName]: prevState.myrecords[companyName].map(el => {
          if(el.SparePartID === sid) {
            return { ...el, Qty: value, TotalPrice: (el.price * value) }
          }
          return el;
        });
      }
    }
  };
}