2

I'm pretty new to ReactJS, I'm liking it a lot, but there are some things like binding that seems to be easier in Angular.

I want to have a form, where a user can click a button to add extra input fields. At any point, they can also "delete" an input field.

On the submit, I want to get these inputs as an array, i.e. pass dynamicInputs to my API which contains an array of name.

This is what I've done (which is probably wrong since I'm treating React like Angular):

var React = require('react');

module.exports = React.createClass({
    addInputField: function(e) {
        e.preventDefault();

        var inputs = this.state.inputs;
        inputs.push({name: null});
        this.setState({inputs : inputs});
    },
    removeInputField: function(index) {
        var inputs = this.state.inputs;
        inputs.splice(index, 1);
        this.setState({inputs : inputs});
    },
    handleSubmit: function (e) {
        e.preventDefault();
        // What do I do here?
    },
    getInitialState: function() {
        return {inputs : []};
    },
    render: function (){
        var inputs = this.state.inputs;
        return (
            // Setting up the form
            // Blah blah
           <div className="form-group">
               <label className="col-sm-3 control-label">Dynamic Inputs</label>
               <div className="col-sm-4">
                   {inputs.map(function (input, index) {
                       var ref = "input_" + index;
                       return (
                           <div className="input-group">
                                <input type="text" className="form-control margin-bottom-12px" placeholder="Enter guid" value={input.name} ref={ref} aria-describedby={ref} />
                                <span className="input-group-addon" onClick={this.removeInputField.bind(this, index)} id={ref} ><i className="fa fa-times"></i></span>
                           </div>
                       )
                   }.bind(this))}
                    <button className="btn btn-success btn-block" onClick={this.addInputField}>Add Input</button>
               </div>
           </div>
        );
    }
});

Right now removeInputField does NOT work! It just removes the last entry all the time.

1
  • Have you checked the console? It should state you must have a key for your <div className="input-group"> Commented Apr 15, 2015 at 23:41

1 Answer 1

2

Every <div className="input-group"> must have a unique key

<div className="input-group" key={index}>

That's how React distinguishes between collection of rendered nodes.

References:

UPD:

As @WiredPrairie mentioned below in the comments - the suggested solution is far from ideal, since the index is not unique enough. And instead you need to create another array with some unique identifiers (a monotonously growing sequence would be enough) and maintain it in parallel with this.state.inputs and use its values as keys.

So, on adding an element you:

this.keys.push(++this.counter);

on removing - remove from both by the same index. And in the .map you

<div className="input-group" key={this.keys[index]}>
Sign up to request clarification or add additional context in comments.

4 Comments

Using index can lead to problems though when dealing with an array where items are removed/added.
@WiredPrairie that's a valid point. Then OP needs to maintain an array of unique values separately.
@WiredPrairie added a fix :-)
@zerkms now i am not have enough knowledge to apply your answer could you please elaborate it, because i am also have this same issue

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.