在react中动态添加多个输入字段

我有一个包含三个输入元素和一个删除按钮的 div。需要的是,当用户单击添加按钮时,它将动态添加此 div,当用户单击删除按钮时,它将删除此 div。我能够使用以下方法动态添加一个输入元素(没有 div 容器)。

  • 在状态变量中创建一个数组。
  • 在数组索引的帮助下为动态输入字段分配一个名称,如 name0、name1

我该如何处理这么多输入字段?当我将整个 div 创建为单独的组件时,问题会进一步扩大。我正在使用基于类的组件。

handleChange=(event) =>
  {
    this.setState({[event.target.name]:event.target.values});
  }

render()
  {
    return(
      <div className="row">
        <button type="button" onClick={this.addElement}>Add</button>
        <div className="col-md-12 form-group">
          <input type="text" className="form-control" name="name" value={this.state.name} onChange={this.handleChange} />
          <input type="text" className="form-control" name="email" value={this.state.email} onChange={this.handleChange} />
          <input type="text" className="form-control" name="phone" value={this.state.phone} onChange={this.state.phone} />
          <button type="button" onClick={this.removeElement}>Remove</button>
        </div> 
      </div>
    )
  }
stack overflow Add multiple input field dynamically in react
原文答案
author avatar

接受的答案

我会从配置的角度来解决这个问题,因为它更具可扩展性。如果你想最终改用 Formik 或 React Form 之类的东西,它会让移动变得更容易一些。

有一个要转换为输入字段的对象数组。您的主组件应该保持状态是否 <Form /> 组件正在显示,以及它是否在配置和任何相关处理程序中可见。

你的表单组件应该维护输入的状态,当你提交它时,将完成的状态传递给父级。

const { Component } = React;

class Example extends Component {

  constructor(props) {
    super();

    // The only state in the main component
    // is whether the form is visible or not
    this.state = { visible: false };
  }

  addForm = () => {
    this.setState({ visible: true });
  }

  removeForm = () => {
    this.setState({ visible: false });
  }

  handleSubmit = (form) => {
    console.log(form);
  }

  render() {

    const { visible } = this.state;
    const { config } = this.props;

    return (

      <div>
        <button
          type="button"
          onClick={this.addForm}
        >Add form
        </button>

        {visible && (
          <Form
            config={config}
            handleSubmit={this.handleSubmit}
            handleClose={this.removeForm}
          />
        )}

      </div>
    );

  }

};

class Form extends Component {

  constructor(props) {
    super();
    this.state = props.config.reduce((acc, c) => {
      return { ...acc, [c.name]: '' };
    }, {});
  }

  handleChange = (e) => {
    const { name, value } = e.target;
    this.setState({ [name]: value });
  }

  handleSubmit = () => {
    this.props.handleSubmit(this.state);
  }

  render() {

    const { name, email, phone } = this.state;
    const { handleClose, config } = this.props;

    return (

      <div onChange={this.handleChange}>

        {config.map(input => {
          const { id, name, type, required } = input;
          return (
            <div>
              <label>{name}</label>
              <input key={id} name={name} type={type} required={required} />
            </div>
          )
        })}

        <button type="button" onClick={this.handleSubmit}>Submit form</button>

        <button type="button" onClick={handleClose}>Remove form</button>

      </div>

    );

  }

}

const config = [
  { id: 1, name: 'name', type: 'text', required: true },
  { id: 2, name: 'email', type: 'email', required: true },
  { id: 3, name: 'phone', type: 'phone', required: true }
];

ReactDOM.render(
  <Example config={config} />,
  document.getElementById('react')
);
input { display: block; }
label { text-transform: capitalize; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

答案:

作者头像

写下如何生成你想要的东西的每一个细节有点困难。因此,我发现为您准备一个 stackblitz 链接以查看它是如何做到的要容易得多,并且该链接已在下面准备好:

generating a dynamic div adding and removing by handling inputs state value

作者头像

我希望这对您的问题有所帮助。我制作了一个具有三个输入标签的子组件。

// parent component
import React, { Component } from "react";
import TextField from "./TextField";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      users: [
        {
          key: Date.now(),
          name: "",
          email: "",
          phone: ""
        }
      ]
    };
  }

  onChange = (inputUser) => {
    this.setState((prevState) => {
      const newUsers = prevState.users.map((element) => {
        if (element.key === inputUser.key) return inputUser;
        return element;
      });
      return { users: newUsers };
    });
  };

  addElement = () => {
    const { name, email, phone } = this.state;
    this.setState((prevState) => ({
      users: prevState.users.concat({
        key: Date.now(),
        name,
        email,
        phone
      })
    }));
  };

  removeElement = (id) => {
    this.setState((prevState) => ({
      users: prevState.users.filter((user) => user.key !== id)
    }));
  };

  render() {
    const { users } = this.state;
    return (
      <div className="row">
        <button type="button" onClick={this.addElement}>
          Add
        </button>
        <div className="col-md-12 form-group">
          {users.map((user) => (
            <React.Fragment key={user.key}>
              <TextField
                value={user}
                onChange={(inputUser) => this.onChange(inputUser)}
              />
              <button
                type="button"
                onClick={() => this.removeElement(user.key)}
                disabled={users.length <= 1}
              >
                Remove
              </button>
            </React.Fragment>
          ))}
        </div>
      </div>
    );
  }
}

export default App;
// child component
import { Component } from "react";

class TextField extends Component {
  handleChange = (ev) => {
    const { name, value } = ev.target;
    this.props.onChange({
      ...this.props.value,
      [name]: value
    });
  };

  render() {
    const { value: user } = this.props;
    return (
      <>
        <input
          className="form-control"
          name="name"
          value={user.name}
          onChange={this.handleChange}
          placeholder="name"
          type="text"
        />
        <input
          className="form-control"
          name="email"
          value={user.email}
          onChange={this.handleChange}
          placeholder="email"
          type="text"
        />
        <input
          className="form-control"
          name="phone"
          value={user.phone}
          onChange={this.handleChange}
          placeholder="phone"
          type="text"
        />
      </>
    );
  }
}

export default TextField;

您还可以在下面的代码框链接中查看代码。 https://codesandbox.io/s/suspicious-heisenberg-xzchm