问题描述
我有一个 JSON
文件,其中包含多个类别,每个类别都有一个名称,该名称带有一组具有各自名称和值的输入字段。
I have a JSON
file with several categories, each category has a name with a set of input fields with their own name and value.
如何使用 setState
更新每个 onChange $的值字段c $ c>?类别和字段使用
map()
呈现。
How can I use setState
to update the value fields of each onChange
? The categories and fields are rendered using map()
.
我能够使它在没有嵌套字段的情况下工作,但在没有嵌套字段的情况下工作。感谢任何帮助。
I am able to make it work without the nested fields but not with. Appreciate any assistance.
[{
"catName": "Category 1",
"fields": [
{
"name": "field 1",
"amount": "0"
},
{
"name": "field 2",
"amount": "0"
}
]
},
{
"catName": "Category 2",
"fields": [
{
"name": "field 1",
"amount": "0"
},
{
"name": "field 2",
"amount": "0"
}
}]
Main.js
Main.js
import React, { Component } from "react";
import Category from "./Category";
import sampleData from "./sampleData";
class Main extends Component {
constructor(props) {
super(props);
this.state = {
list: sampleData
};
}
handleChange = e => {
this.setState({ ??? });
};
render() {
return (
<div>
{this.state.list.map(item => (
<Category
id={item.catName}
name={item.catName}
key={item.catName}
list={item}
handleChange={this.handleChange}
/>
))}
</div>
);
}
}
export default Main;
Category.js
Category.js
import React from "react";
import Item from "./Item";
const Category = ({ name, list, handleChange }) => {
return (
<div className="section">
<h3>{name}</h3>
{list.fields.map(item => (
<Item
id={item.name}
name={item.name}
key={item.name}
list={item}
handleChange={handleChange}
/>
))}
</div>
);
};
export default Category;
Item.js
Item.js
import React from "react";
const Item = ({ list, handleChange }) => {
return (
<div className="item">
<label className="label">{list.name}</label>
<input
name={list.name}
id={list.name}
className="input"
type="text"
onChange={handleChange}
value={list.amount}
/>
</div>
);
};
export default Item;
推荐答案
将类别和项目索引传递给您的 handleChange
函数。使用这些索引来更新数组中的正确项目。通过不做操作来避免状态突变
Pass the category and item index to your handleChange
function. Use those index to update the correct item in the array. Avoid state mutation by not doing
// state mutation
this.state.list[categoryIndex].fields[fieldIndex].amount = e.target.value
handleChange函数
handleChange function
handleChange = (e, categoryIndex, itemIndex) => {
const { list } = this.state;
const fields = [...list[categoryIndex].fields.slice(0, itemIndex),
Object.assign({}, list[categoryIndex].fields[itemIndex], { amount: e.target.value }),
...list[categoryIndex].fields.slice(itemIndex + 1)
]
this.setState({
list: [...list.slice(0, categoryIndex),
Object.assign({}, list[categoryIndex], { fields }),
...list.slice(categoryIndex + 1)
]
})
}
项目组件,添加类别和归档索引作为道具。
Item component, add category and filed index as props.
import React from "react";
const Item = ({ list, handleChange, categoryIndex, itemIndex, value }) => {
return (
<div className="item">
<label className="label">{list.name}</label>
<input
name={list.name}
id={list.name}
className="input"
type="text"
value={value}
onChange={(e) => handleChange(e, categoryIndex, itemIndex)}
/>
</div>
);
};
export default Item;
类别部分
import React from "react";
import Item from "./Item";
const Category = ({ name, list, handleChange, categoryIndex }) => {
return (
<div className="section">
<h3>{name}</h3>
{list.fields.map((item, index) => (
<Item
id={item.name}
name={item.name}
key={item.name}
list={item}
categoryIndex={categoryIndex}
itemIndex={index}
value={item.amount}
handleChange={handleChange}
/>
))}
</div>
);
};
export default Category;
演示
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
<div id="root"></div>
<script type="text/babel">
const Item = ({ list, handleChange, categoryIndex, itemIndex, value }) => {
return (
<div className="item">
<label className="label">{list.name}</label>
<input
name={list.name}
id={list.name}
className="input"
type="text"
value={value}
onChange={(e) => handleChange(e, categoryIndex, itemIndex)}
/>
</div>
);
};
const Category = ({ name, list, handleChange, categoryIndex }) => {
return (
<div className="section">
<h3>{name}</h3>
{list.fields.map((item, index) => (
<Item
id={item.name}
name={item.name}
key={item.name}
list={item}
categoryIndex={categoryIndex}
itemIndex={index}
value={item.amount}
handleChange={handleChange}
/>
))}
</div>
);
};
class App extends React.Component {
constructor() {
super();
this.state = {
name: 'React',
show: false,
list: [
{
"catName": "Category 1",
"fields": [
{
"name": "field 1",
"amount": "0"
},
{
"name": "field 2",
"amount": "0"
}
]
},
{
"catName": "Category 2",
"fields": [
{
"name": "field 1",
"amount": "0"
},
{
"name": "field 2",
"amount": "0"
}
]
}
]
};
}
handleChange = (e, categoryIndex, itemIndex) => {
const { list } = this.state;
const fields = [...list[categoryIndex].fields.slice(0, itemIndex),
Object.assign({}, list[categoryIndex].fields[itemIndex], { amount: e.target.value }),
...list[categoryIndex].fields.slice(itemIndex + 1)
]
this.setState({
list: [...list.slice(0, categoryIndex),
Object.assign({}, list[categoryIndex], { fields }),
...list.slice(categoryIndex + 1)
]
})
}
show = () => {
this.setState({
show: true
})
}
render() {
return (
<div>
{this.state.list.map((item, index) => (
<Category
id={item.catName}
name={item.catName}
key={item.catName}
categoryIndex={index}
list={item}
handleChange={this.handleChange}
/>
))}
<br />
<button onClick={this.show}>Show changes</button>
{this.state.show &&
<pre>
{JSON.stringify(this.state.list, null, 4)}
</pre>
}
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
</script>
这篇关于如何设置映射输入的嵌套JSON数组对象的状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!