首页 > 解决方案 > 如何在 React 中正确实现嵌套的动态表单

问题描述

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

"basketData": [
        {
            "finalTransfer": "",
            "averageDistance": ""
            "shares": [
                "share01": "6",
                "share02": "10",
            ]
        },
        {
            "finalTransfer": "",
            "averageDistance": ""
            "shares": [
                "share01": "21",
                "share02": "18",
                "share03": "7",
                "share04": "32",
            ]
        }
]

我希望能够通过表单动态添加多个购物篮数据,并在每个购物篮数据中动态添加共享字段。

这是我的测试 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);

通过上面的实现,我得到了一个1 个 basketData的输出,不幸的是它不能满足我的需要。

"basketData": [
        {
            "basketData": [
                {
                    "finalTransfer": "",
                    "averageDistance": ""
                }
            ],
            "shares": [
                {
                    "share": 0
                },
                {
                    "share": 0
                }
            ],
            "finalTransfer": "100",
            "averageDistance": "180"
        }
]

我怎样才能正确实施它?

标签: javascriptreactjs

解决方案


好像你忘记了列表的键。这就是您在列表中获得重复数据的原因。

如果您像这样映射数组,则需要为每个项目添加一个唯一键:但尽量不要使用索引,而是使用唯一 id,可能会自动生成以处理删除。

是您的代码的工作沙箱。


推荐阅读