admin管理员组

文章数量:1356873

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

本文标签: javascriptHow to Update JSON Object39s state for onChange event in REACT JSStack Overflow