Reputation: 97
Why is this.refs
undefined in the code below?
class NewItem extends React.Component {
handleClick() {
console.log(this.refs) //prints out undefined
const name = this.refs.name.value;
const description = this.refs.description.value;
$.ajax({
url: 'api/v1/items',
type: 'POST',
data: {
item: {
name: name,
description: description
}
},
success: (item) => {
this.props.handleSubmit(item);
}
});
}
render() {
return (
<div>
<input ref='name' placeholder='Enter the name of the item' />
<input ref='description' placeholder='Enter the description of the item' />
<button onClick={this.handleClick}>Submit</button>
</div>
)
}
}
Upvotes: 2
Views: 10496
Reputation: 4481
You havens bind the functions. it should be done like this
class NewItem extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log(this.refs) //prints out undefined
const name = this.refs.name.value;
const description = this.refs.description.value;
$.ajax({
url: 'api/v1/items',
type: 'POST',
data: {
item: {
name: name,
description: description
}
},
success: (item) => {
this.props.handleSubmit(item);
}
});
}
render() {
return (
<div>
<input ref='name' placeholder='Enter the name of the item' />
<input ref='description' placeholder='Enter the description of the item' />
<button onClick={this.handleClick}>Submit</button>
</div>
)
}
}
Try using the ES6 features, The arrow functions to avoid this binding issue. like this.
handleClick =()=> {
console.log(this.refs) //prints out undefined
const name = this.refs.name.value;
const description = this.refs.description.value;
$.ajax({
url: 'api/v1/items',
type: 'POST',
data: {
item: {
name: name,
description: description
}
},
success: (item) => {
this.props.handleSubmit(item);
}
});
}
Upvotes: 0
Reputation: 59511
You need to bind this
to your handleClick()
function, like this:
<button onClick={this.handleClick.bind(this)}>Submit</button>
or through the constructor, like this:
constructor(props) {
...
this.handleClick = this.handleClick.bind(this);
}
Though you should avoid using string literals in refs
. This approach is deprecated.
Legacy API: String Refs
If you worked with React before, you might be familiar with an older API where the
ref
attribute is a string, like"textInput"
, and the DOM node is accessed asthis.refs.textInput
. We advise against it because string refs have some issues, are considered legacy, and are likely to be removed in one of the future releases. If you're currently usingthis.refs.textInput
to access refs, we recommend the callback pattern instead.
Instead do:
constructor(props) {
this.nameInputRef;
this.descriptionInputRef;
}
...
<input ref={(el) => {this.nameInputRef = el;} placeholder='Enter the name of the item' />
<input ref={(el) => {this.descriptionInputRef = el;} placeholder='Enter the description of the item' />
Upvotes: 1
Reputation: 130102
The method is not bound to this
when used as a function:
<button onClick={this.handleClick.bind(this)}>Submit</button>
or
<button onClick={event => this.handleClick(event)}>Submit</button>
or bind it in constructor
:
constructor(props, context) {
super(props, context);
this.handleClick = this.handleClick.bind(this);
}
Upvotes: 8