How to automatically generate Input fields related to list of items React.JS

Tags: ,



I’m having a problem in dynamically generating input fields in react. So I have a keys state and I need to have an input field for each key and also I have tried this link: How to implement a dynamic form with controlled components in ReactJS? but the problem is that the my values state is empty so it will render nothing regarding keys and when I did it with this.ModifyList() it shows input fields regarding each key but it does not have onChange mehtod. the onChange method causes the error when using the this.createUI() . Also in the end I would like to submit the values of input fields.

Is there any suggestion on how to solve this problem?

my Code Below:

export class FileUploadComponent extends Component {
    constructor(props) {
        super(props);
        this.state = {
            //Keys: [],
            //values: [],
            modify: { Keys: ['key1' , 'key2' , 'key3'], values: [] }

        }
        this.handleSubmit = this.handleSubmit.bind(this);

    }
    
    createUI() {
        const { modify } = this.state;
        const keys = modify.Keys
        const values = modify.values
        const val = keys.map(function (item, i) {
            values.map(function (el, i) {
                return <div key={i}>
                    <label>{item}</label>
                    <input type="text" onChange={this.handleChange.bind(this, i)} />
                </div>
            })

        });
        return val;
    }
    
    handleChange(event, i) {
        const {modify} = this.state;
        let values = [...modify.values];
        values[i] = event.target.value;
        this.setState({ values: values });

    }
    handleSubmit(event) {
        alert('A name was submitted: ' + this.state.values.join(', '));
        event.preventDefault();
    }

    ModifyList() {
        const { modify } = this.state;
        const keys = modify.Keys
        const val = keys.map(function (item, i) {
            return <div>
                <label>{item}</label>
                <input type="text" />
            </div>

        });
        return val;
    }
        render() {
        return (
            <div>
                <form onSubmit={this.handleSubmit}>
                    {/*this.ModifyList()*/}
                    {this.createUI()}
                    <input type="submit" className="btn btn-primary" value="Search !" />
                     <input type="submit" className="btn btn-primary" value="Edit !" />
                 </form>
             </div>
        )
    }
}

export default FileUploadComponent

Answer

You have some some scope issue. One of the main difference between a fat-arrow function and a function declared with the function keyword is that the latter has its own scope, meaning that if you call this inside of it, you are referencing its scope.

In your createUI function, switch your functions to fat-arrow functions and you are all set. Just remember to bind your handle change function in your constructor.

export class FileUploadComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
      //Keys: [],
      //values: [],
      modify: { Keys: ["key1", "key2", "key3"], values: [""] }
    };

    this.handleSubmit = this.handleSubmit.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }

  createUI() {
    const { modify } = this.state;
    const keys = modify.Keys;
    const values = modify.values;
    
    const val = keys.map((item, i) => {
      return values.map((el, i) => {
        return (
          <div key={i}>
            <label>{item}</label>
            <input
              type="text"
              onChange={(event) => this.handleChange(event, i)}
            />
          </div>
        );
      });
    });
    return val;
  }

  handleChange(event, i) {
    const { modify } = this.state;
    let values = [...modify.values];
    values[i] = event.target.value;
    this.setState({ values: values });
  }

  handleSubmit(event) {
    alert("A name was submitted: " + this.state.values.join(", "));
    event.preventDefault();
  }

  ModifyList() {
    const { modify } = this.state;
    const keys = modify.Keys;
    const val = keys.map(function (item, i) {
      return (
        <div>
          <label>{item}</label>
          <input type="text" />
        </div>
      );
    });
    return val;
  }

  render() {
    return (
      <div>
        <form onSubmit={this.handleSubmit}>
          {/*this.ModifyList()*/}
          {this.createUI()}
          <input type="submit" className="btn btn-primary" value="Search !" />
          <input type="submit" className="btn btn-primary" value="Edit !" />
        </form>
      </div>
    );
  }
}


Source: stackoverflow