Как обновить состояние объекта JSON для события onChange в REACT JS? - PullRequest
0 голосов
/ 03 мая 2019

У меня есть состояние myrecords [] , которое содержит JSON Object в следующем формате:

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

Теперь я показываю эту запись в реагирующих js таким образом, что все элементы отображаются в строках и сгруппированы по их CompanyNames и для каждого элемента, который есть.поле ввода для количества. Кол-во равно 1 по умолчанию для всех, поэтому TotalPrice совпадает с UnitPrice.

Теперь я хочу, чтобы onChange любого конкретного поля ввода Кол-во соответствовал Элемент TotalPrice в объекте JSON Object также должен обновляться в состоянии myrecords [] .Также Кол-во также должно обновляться в состоянии myrecords [].

PS: 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 ]

1 голос
/ 03 мая 2019

Вы пытаетесь найти предмет в this.state.myrecord. Но вы должны в конкретной компании. Вот это ДЕМО .

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>
1 голос
/ 03 мая 2019

Проблема в том, что this.state.myrecords - это объект, поэтому напрямую мы не можем использовать find для этого.Также вам необходимо использовать функцию обновления (см. Документацию для получения более подробной информации) .

Решение вашей проблемы: Передайте companyName также в функции onChange, затем выполните цикл только для определенных сведений о компании.массив.Передав название компании, вы сможете легко обновить состояние, в противном случае вам нужно запустить цикл для всех массивов.

Например:

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;
        });
      }
    }
  };
}
1 голос
/ 03 мая 2019

Сначала измените это

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

Внимание! Код не проверен.Пожалуйста, проверьте и дайте мне знать:)

...