Reputation: 1223
On my way to learn React and ES6, I took the official tutorial and played around to make it ES6 compatible. But when it comes to executing the Ajax request, I get the following error:
CommentBox.js:23 Uncaught TypeError: Cannot read property 'url' of undefined
Here is my CommentBox file/code:
import React from 'react';
import CommentList from './CommentList.js';
import CommentForm from './CommentForm.js';
export default class CommentBox extends React.Component {
constructor(props) {
super(props);
console.log(this.props)
this.state = {
data: []
}
}
loadCommentsFromServer() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
}
handleCommentSubmit(comment) {
let comments = this.state.data;
// Optimistically set id on the new comment.
// It will be replaced by an id generated by the server.
// In a production you would have a more robust system in place.
comment.id = Date.now();
let newComments = comments.concat([comment]);
this.setState({data: newComments});
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'POST',
data: comment,
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
this.setState({data: comments});
console.error(this.props.url, status, err.toString());
}.bind(this)
});
}
componentDidMount() {
this.loadCommentsFromServer();
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
}
render() {
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>
);
}
}
The error happen on loadCommentsFromServer
; it seems not to know what this.props
is. I thought it was a this reference problem and found a similar question where it is suggested to use new ES6 arrows to fix the issue. I then tried: loadCommentsFromServer = () => {}
, but Browserify complains and doesn't build.
Upvotes: 1
Views: 2322
Reputation: 52133
I thought it was a this reference problem and googling around i found a similar stackoverflow question where they suggest to use new ES6 arrows to fix the issue. I try then to use:
loadCommentsFromServer = () => {}
but browserify complain and don't build :/
ES6 arrow functions will indeed solve your problem. The build error is because ES6 does not support class properties, and loadCommentsFromServer =
is a class property initializer. Enable ES7 class properties and you should be able to do this and it will solve your problem without needing to manually bind
or wrap your callback in a new fat arrow function when you call setInterval
.
Upvotes: 1
Reputation: 5298
This line is your problem:
setInterval(this.loadCommentsFromServer, this.props.pollInterval);
You are passing the method loadCommentsFromServer
to setInterval
, but it will be invoked without context therefore this
will no longer bound to your component (this
will be bound to the window). Instead you should do something like this:
setInterval(this.loadCommentsFromServer.bind(this), this.props.pollInterval);
// OR... use a fat arrow, which preserves `this` context
setInterval(() => this.loadCommentsFromServer(), this.props.pollInterval);
Finally, you should store the interval id, so that you can clear it when your component is unmounted:
componentDidMount() {
this.loadCommentsFromServer();
this.intervalId = setInterval(this.loadCommentsFromServer, this.props.pollInterval);
},
componentWillUnmount() {
clearInterval(this.intervalId);
}
Upvotes: 6