I am trying to implement a nested dynamic form in using React class component with the following JSON output:
"basketData": [
{
"finalTransfer": "",
"averageDistance": ""
"shares": [
"share01": "6",
"share02": "10",
]
},
{
"finalTransfer": "",
"averageDistance": ""
"shares": [
"share01": "21",
"share02": "18",
"share03": "7",
"share04": "32",
]
}
]
I want to be able to add multiple basketData dynamically via the form as well as add shares fields dynamically in each basketData.
Here is what my test GUI looks like:

Following few examples I have the implementation below so far, however the JSON output is incorrect.
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);
With the above implementation, I get a the output below for a 1 basketData which unfortunately does not meet my need.
"basketData": [
{
"basketData": [
{
"finalTransfer": "",
"averageDistance": ""
}
],
"shares": [
{
"share": 0
},
{
"share": 0
}
],
"finalTransfer": "100",
"averageDistance": "180"
}
]
How can I implement it correctly ?