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

时间:2019-05-03 04:17:01

标签: javascript json reactjs state onchange

我的状态为 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"
            }
        ]
    }
}

现在,Im在react js中显示此记录的方式是,所有项目都按行显示并按其 CompanyNames 分组,并且每个项目都有一个“数量”输入字段。 默认数量为1 ,因此TotalPrice与UnitPrice相同。

现在,我希望数量的任何特定输入字段的onChange,JSON Object 中相应的 TotalPrice 项目也应在 myrecords [] 状态。同样,数量也应在 myrecords []状态下得到更新。

P.S: myrecords [] 包含JSON 对象,而不是数组。

这是我的用于显示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
   });
}

3 个答案:

答案 0 :(得分:1)

首先更改此

{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
   });
}

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

答案 1 :(得分:1)

您正在尝试在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>

答案 2 :(得分:1)

问题是this.state.myrecords是一个对象,因此我们不能直接在其上使用find。另外,您需要使用here

您的问题的解决方案是:在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;
        });
      }
    }
  };
}