最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to Update JSON Object's state for onChange event in REACT JS? - Stack Overflow

programmeradmin0浏览0评论

I have state of myrecords[] which contains JSON Object in the following format:

{
    "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"
            }
        ]
    }
}

I have state of myrecords[] which contains JSON Object in the following format:

{
    "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"
            }
        ]
    }
}

Now Im showing this record in react js in a way that all items are displayed in rows and grouped by their CompanyNames and against each Item there is an input field for Quantity. Qty is 1 as default for all so TotalPrice is same as UnitPrice.

Now I want that onChange of any particular input field of Qty, the corresponding TotalPrice item in the JSON Object should also get updated in myrecords[] state. Also the Qty should also get updated in state of myrecords[].

P.S: myrecords[] contains JSON object not array.

here is my react code for showing JSON object record:

  
  {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>

  ))}

And the onChangeQty function is as follows**(this is where I need help)**:

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

Share Improve this question asked May 3, 2019 at 4:17 YellowMinionYellowMinion 2422 gold badges10 silver badges26 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 2

First change this

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

to

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

Because we already using i in above map also.

And then change this

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

to

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

And then your onChange should be

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

If you don't like index based onChange you can also do like below(sid based). just pass CompanyName,sid,e) on this function 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
   });
}

Warning: Code not tested. Please check and let me know :)

You are trying to find an item in this.state.myrecord. But you should in the specific pany. Here is the 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 = (panyName, sid, e) => {
    const { records } = this.state;

    const newQty = e.target.value;

    this.setState({
      records: {
        ...records,
        [panyName]: records[panyName].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./ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Issue is this.state.myrecords is an object, so directly we can't use find on that. Also you need to use updater function (check doc for more details).

Solution to your problem is: Pass the panyName also in onChange function, then run the loop only of specific pany details array. Passing pany name will help you to update the state easily, otherwise you need to run the loop on all the arrays.

Like this:

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

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

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

评论列表(0)

  1. 暂无评论