Javascript 如何在React中正确实现嵌套动态表单

Javascript 如何在React中正确实现嵌套动态表单,javascript,reactjs,Javascript,Reactjs,我正在尝试使用React类组件实现一个嵌套的动态表单,该组件具有以下JSON输出: "basketData": [ { "finalTransfer": "", "averageDistance": "" "shares": [ "share01&q

我正在尝试使用React类组件实现一个嵌套的动态表单,该组件具有以下JSON输出:

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