Javascript 如何在React中正确实现嵌套动态表单
我正在尝试使用React类组件实现一个嵌套的动态表单,该组件具有以下JSON输出:Javascript 如何在React中正确实现嵌套动态表单,javascript,reactjs,Javascript,Reactjs,我正在尝试使用React类组件实现一个嵌套的动态表单,该组件具有以下JSON输出: "basketData": [ { "finalTransfer": "", "averageDistance": "" "shares": [ "share01&q
"basketData": [
{
"finalTransfer": "",
"averageDistance": ""
"shares": [
"share01": "6",
"share02": "10",
]
},
{
"finalTransfer": "",
"averageDistance": ""
"shares": [
"share01": "21",
"share02": "18",
"share03": "7",
"share04": "32",
]
}
]
我希望能够通过表单动态添加多个basketData,并在每个basketData中动态添加共享字段
以下是我的测试GUI的外观:
下面是几个示例,到目前为止,我在下面介绍了实现,但是JSON输出是不正确的
class Step3a extends React.Component {
constructor(props) {
super(props);
this.state = {
baskets: [{ finalTransfer: "", averageDistance: "" }],
shares: [{ share: "" }],
};
}
handleChange = (index, event) => {
const { name, value } = event.target;
const values = [...this.state.baskets];
values[index][name] = value;
this.setState({ values });
};
addBasket = () => {
this.setState((prevState) => ({
baskets: [
...prevState.baskets,
{ finalTransfer: "", averageDistance: "" },
],
}));
};
removeBasket = (index, event) => {
let baskets = [...this.state.baskets];
baskets.splice(index, 1);
this.setState({ baskets });
};
handleShareChange = (idx) => (event) => {
const newShares = this.state.shares.map((share, sidx) => {
if (idx !== sidx) return share;
return { ...share, name: event.target.value };
});
this.setState({ shares: newShares });
};
handleAddShare = () => {
this.setState({
shares: this.state.shares.concat([{ name: "" }]),
});
};
handleRemoveShare = (idx) => () => {
this.setState({
shares: this.state.shares.filter((s, sidx) => idx !== sidx),
});
};
isValidated() {
return true;
}
render() {
const { classes } = this.props;
let { baskets, shares } = this.state;
return (
<GridContainer justify="center">
<GridItem xs={12} sm={12}>
<h4 className={classes.infoText}>How about you add a baskets</h4>
</GridItem>
<GridItem xs={12} sm={12}>
{baskets.map((val, idx) => {
return (
<Card>
<CardContent>
<GridItem xs={12} sm={12}>
<h4>BasketData {idx + 1}</h4>
</GridItem>
<GridItem xs={12} sm={4}>
<TextField
fullWidth={true}
name="finalTransfer"
label="Final Transfer"
value={val.finalTransfer}
onChange={(event) => this.handleChange(idx, event)}
/>
</GridItem>
<GridItem xs={12} sm={4}>
<TextField
fullWidth={true}
name="averageDistance"
label="Average Distance"
value={val.averageDistance}
onChange={(event) => this.handleChange(idx, event)}
/>
</GridItem>
<Card>
<CardContent>
{shares.map((share, index) => {
return (
<GridItem xs={12} sm={4}>
<input
type="text"
placeholder={`Share #${index + 1} name`}
value={share.name}
onChange={this.handleShareChange(index)}
/>
<button
type="button"
onClick={this.handleRemoveShare(index)}
className="small"
>
Remove Share
</button>
</GridItem>
);
})}
<GridItem>
<button
type="button"
onClick={this.handleAddShare}
className="small"
>
Add Share
</button>
</GridItem>
</CardContent>
</Card>
<GridItem xs={12} sm={4}>
<Button
color="rose"
className={"Submit"}
onClick={(event) => this.removeBasket(idx, event)}
>
Remove BasketData
</Button>
</GridItem>
</CardContent>
</Card>
);
})}
</GridItem>
<GridItem xs={12} sm={4}>
<Button color="rose" className={"Submit"} onClick={this.addBasket}>
Add BasketData
</Button>
</GridItem>
</GridContainer>
);
}
}
Step3a.propTypes = {
classes: PropTypes.object,
};
export default withStyles(style)(Step3a);
如何正确实现它?似乎您忘记了列表的一个键。这就是为什么列表中会出现重复数据 如果映射这样的数组,则需要为每个项添加一个唯一的键:但不要尝试使用索引,而是使用一个唯一的id,可能是自动生成的以处理删除
是您代码的一个工作沙盒。似乎您忘记了列表的一个键。这就是为什么列表中会出现重复数据 如果映射这样的数组,则需要为每个项添加一个唯一的键:但不要尝试使用索引,而是使用一个唯一的id,可能是自动生成的以处理删除
是您代码的工作沙盒。谢谢您的回答!我看了一下沙箱,结果仍然不是我上面描述的那样。预期的输出如我文章中的第一个JSON示例所示,因此嵌套仍然不是我想要的。此外,我从您的回答中注意到,例如,当我单击“添加共享”并在BasketData_1中添加共享时,相同的共享会添加到BasketData_2中(或在其他BasketData中重复)。谢谢你的回答!我看了一下沙盒,输出仍然不是我上面描述的。预期的输出如我文章中的第一个JSON示例所示,因此嵌套仍然不是我想要的。此外,我从你的回答中注意到,当我单击“添加共享”时并在BasketData_1中添加共享。例如,在BasketData_2中添加相同的共享(或在其他BasketData中重复)。
"basketData": [
{
"basketData": [
{
"finalTransfer": "",
"averageDistance": ""
}
],
"shares": [
{
"share": 0
},
{
"share": 0
}
],
"finalTransfer": "100",
"averageDistance": "180"
}
]