Reputation: 319
I am getting an issue using react, where I'm trying to click on a list item and invoke a method, chooseTopic, for the class but I'm getting returned "Uncaught TypeError: _this3.chooseTopic is not a function ReactJS"
Here is roughly my class:
class Topicselect extends Component {
constructor(props){
super(props);
this.state = {
topics: ['math','english','science']
}
}
chooseTopic(){
console.log('has been clicked')
}
render(){
const topics = this.state.topics.map(function(topic, i){
return(<li key={i} onClick={() => this.chooseTopic()}>{topic}
</li>)
})
return(
<div className="topicselect">
<ul>
<p onClick={()=> this.chooseTopic()}>hello world</p>
{topics}
</ul>
</div>
)
}
}
export default Topicselect;
when I clicked the hello world paragraph it invokes the function, however when I click the list items it gives me the error, Uncaught TypeError: _this3.chooseTopic is not a function ReactJS
any ideas?
Upvotes: 2
Views: 9615
Reputation: 1
The this
object has no reference. In React, the callback function or event handler does not know that it is part of the react Component
class.
this
object can be bound or an arrow function syntax used when referencing the callback (event handler).
This concept is presented in React: this is null in event handler.
Not sure if this code will work in your situation. For demonstration purposes:
return(<li key={i} onClick={ this.chooseTopic.bind(this) }>{topic}
or
return(<li key={i} onClick={(e) => this.chooseTopic(e)}>{topic}
You may need to modify the signature of your event handler to accept the event object:
chooseTopic(e){
...
Upvotes: 0
Reputation: 15513
You need to bind this
``` constructor(props) { // Other stuff
// This binding is necessary to make this
work in the callback
this.chooseTopic = this.chooseTopic.bind(this);
}
```
You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.
This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method.
If calling bind annoys you, there are two ways you can get around this. If you are using the experimental property initializer syntax, you can use property initializers to correctly bind callbacks:
https://facebook.github.io/react/docs/handling-events.html
Upvotes: 0
Reputation: 57974
That's because you're using a function for your Array#map
callback. Use an arrow function:
const topics = this.state.topics.map((topic, i) => {
return (
<li key={i} onClick={() => this.chooseTopic()}>
{topic}
</li>
)
})
The reason is because, in a function expression, this
won't refer to your component, it depends on how it's called. Since this
isn't referring to the component, chooseTopic
isn't found as a method thus the error. An arrow function does not bind this
and thus refers to the this
of the enclosing scope -- the component.
Upvotes: 7