简体   繁体   中英

React.js: Add/Remove input field on click of a button

React.js: Add/Remove input field on click of a button:

When a user click Add, I want a new input field to be added.

The name property is changing for every input, by increment the number in the middle:

document-0-document document-1-document

I receive the following error:

"TypeError: this is undefined var arr = this.state.documents;"

I have an idea what is creating the error but I didn't found a fix.

HTML Code.

<fieldset class="fieldset">
  <input type="file" name="document-0-document">
  <div class="more-documents">
    <input type="file" name="document-1-document">
    <button data-reactid=".0.1">Add</button>
  </div>
 </fieldset>

Main Component code:

class DocumentsFieldSet extends Component{

  constructor(props){
      super(props);
      this.state = {documents:[]}
  }

  add(i) {
      var arr  = this.state.documents;
      arr.push(i);
      this.setState({documents: arr});
  }

  eachDocument () {
      return <DocumentInput key={i}/>
  }

  render (){
      return (
        <div>
            {this.state.documents.map(this.eachDocument)}
            <button onClick={this.add.bind()}>Add</button>
        </div>
      )
  }
}

ReactDOM.render(<DocumentsFieldSet/>, document.querySelector ('.more-    documents'))

Component Code

class DocumentInput extends Component {
  render() {
      return <input type="file" name="document-{i}-document" ref="" />;
  }
}

export default DocumentInput;

You have several mistakes in your example

  1. You need bind this for .add method

  2. You don't put to this.state.documents array index

  3. Inside DocumentInput there is no i variable

 class DocumentInput extends React.Component { render() { return <input type="file" name={ `document-${ this.props.index }-document` } />; } } class DocumentsFieldSet extends React.Component{ constructor(props){ super(props); this.state = { documents: [] } this.add = this.add.bind(this); } add() { const documents = this.state.documents.concat(DocumentInput); this.setState({ documents }); } render () { const documents = this.state.documents.map((Element, index) => { return <Element key={ index } index={ index } /> }); return <div> <button onClick={ this.add }>Add</button> <div className="inputs"> { documents } </div> </div> } } ReactDOM.render( <DocumentsFieldSet />, document.getElementById('container') ); 
 .inputs { margin: 5px 0; padding: 10px; border: 2px solid #000; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="container"></div> 

Maybe you forgot to pass context into bind function.

replace

<button onClick={this.add.bind()}>Add</button>

to

<button onClick={this.add.bind(this)}>Add</button>

Write your add function as an arrow function. It would bind function to this for you. Read more about it here

add = (i) => {
    var arr = this.state.documents;
    arr.push(i);
    this.setState({documents: arr});
};

Also I would rewrite your function to be:

add = (i) => {
    const { documents } = this.state;
    documents.push(i);
    this.setState({ documents });
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM