如何在 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;
});
}
}
};
}
我有 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;
});
}
}
};
}