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;
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;
Share
Improve this question
edited Jan 4, 2018 at 3:15
grantnz
7,4231 gold badge32 silver badges38 bronze badges
asked Jul 26, 2016 at 12:59
user3541631user3541631
4,00811 gold badges54 silver badges123 bronze badges
1
- What you want to add? – Alessander Franca Commented Jul 26, 2016 at 13:05
3 Answers
Reset to default 13You have several mistakes in your example
You need bind
this
for.add
methodYou don't put to
this.state.documents
array indexInside
DocumentInput
there is noi
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 });
};