ReactJs - 单击按钮时添加一个组件

ReactJs - Add a component when click button

我有一个找不到解决办法的困境。我想导入许多产品,但它们可能属于同一类别,所以当我单击“+”时,显示会添加类似图片的行 我在互联网上看到了很多教程并按照它们进行了操作,但它们都失败了。我不知道该怎么做。请帮我!非常感谢

state = {
  listItems: [],
  userInput: this.need,
}

need = {
  category: "",
  name: "",
  quantity: ""
}
    handleChange = (event) => {
        const target = event.target;
        const value = target.value;
        const name = target.name;
        let userInput = { ...this.state.userInput };
        userInput[name] = value;
        this.setState({ userInput });
    }
    submitHandler = e => {
        e.preventDefault()
        this.setState({
            listItems: [...this.state.listItems, this.state.userInput],
        })
    }
<Form>
<Form.Group id="need">
    <Row>
     <Col md="3">
       <label>Category</label>
       <select name="category" className="form-control" onChange={this.handleChange}>
         <option value="1">Water</option>
         <option value="2">Food</option>
       </select>
    </Col>
    <Col md="4">
      <label>Name</label>
        <Input
           name="name"
           className="form-control-alternative"
           onChange={this.handleChange}
           type="text"
         />
    </Col>
    <Col md="4">
      <label>Quantity</label>
      <Input
        name="quantity"
        className="form-control-alternative"
        type="text"
        onChange={this.handleChange}
      />
   </Col>
   <Col>
<i style={{ marginTop: 45 }} onClick={submitHandler} >Add more</i>
   </Col>
</Row>
</Form.Group>
</Form>

CodeSandbox!

对于这种形式,我更喜欢使用formik而不是this.setState

解决方案 1. this.setState

我会这样设计状态

this.state = {
  form: [
    {
      category: "",
      name: "",
      quantity: 0,
    },
  ],
};

以及添加更多项目的方法,编辑它们的内容

handleAdd = () => {
  this.setState({
    form: [
      ...this.state.form,
      {
        category: "",
        name: "",
        quantity: 0,
      },
    ]
  });
};

handleEditFieldOfItem = (event, itemIndex, fieldName) => {
  const value = event.target.value;
  this.setState({
    form: this.state.form.map((item, index) => {
      if (index === itemIndex) {
        return { ...item, [fieldName]: value };
      }
      return item;
    })
  });
};

我会将这些项目呈现如下:

render() {
  return (
    <div>
      {this.state.form.map((item, index) => {
        return (
          <div key={index}>
            <div>
              <select value={item.category} onChange={(event) => { this.handleEditFieldOfItem(event, index, 'category'); }}>
                <option value="water">Water</option>
                <option value="food">Food</option>
              </select>
            </div>
            <div>
              <input type="text" value={item.name} onChange={(event) => { this.handleEditFieldOfItem(event, index, 'name'); }} />
            </div>
            <div>
              <input type="text" value={item.quantity} onChange={(event) => { this.handleEditFieldOfItem(event, index, 'quantity'); }} />
            </div>
          </div>
        );
      })}
      <button onClick={this.handleAdd}>Add</button>
    </div>
  );
}

解决方案 2. 使用 Formik(带有 FieldArray 组件)

Formik 具有验证、处理嵌套值的能力,...

您应该先查看 Formik documentation

import { Formik, Field, FieldArray } from "formik";

// ...

<Formik
  initialValues={{
    form: [
      {
        category: "",
        name: "",
        quantity: 0
      }
    ]
  }}
  onSubmit={(values, helpers) => {
    // 
  }}
>
  {(formikProps) => {
    const { values, handleSubmit } = formikProps;
    return (
      <>
        <FieldArray name="form">
          {(arrayHelpers) => {
            return (
              <div>
                {values.form.map((item, index) => {
                  return (
                    <div key={index}>
                      <Field as="select" name={`form.${index}.category`}>
                        <option value="water">Water</option>
                        <option value="food">Food</option>
                      </Field>
                      <Field name={`form.${index}.name`} />
                      <Field name={`form.${index}.quantity`} />
                    </div>
                  );
                })}
                <div>
                  <button onClick={() => arrayHelpers.push({ category: '', name: '', quantity: 0 })}>Add</button>
                </div>
              </div>
            )}}
        </FieldArray>
        <button type="submit">Submit</button>
      </>
    );
  }}
</Formik>