Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ES6/React "this" keyword with ajax to get data from server (tutorial) [duplicate]

I'm following the React Beginner Tutorial and I'm trying to translate it into ES6. However when I changed the CommentBox to an ES6 class it started giving me a this.props.url is undefined error (in the AJAX call in loadCommentsFromServer). I think this has something to do with how ES6 binds this, but this I'm not very familiar with the language (nor React) so I'm not sure. I've looked at the React 0.13 release notes and saw this:

React.createClass has a built-in magic feature that bound all methods to this automatically for you. This can be a little confusing for JavaScript developers that are not used to this feature in other classes, or it can be confusing when they move from React to other classes.

I'm not exactly sure but I thought that it meant I had to save the value of this (as in let that = this and .bind(that)) but that also gave the same this.props.url is undefined - I'm not sure where to go next.

Here's my current code:

class CommentBox extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: []
    };
  }
  loadCommentsFromServer() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      cache: false,
      success: function(data) {
        this.setState({
          data: data
        })
      }.bind(this)
    });
  }
  handleCommentSubmit(comment) {
    var comments = this.state.data;
    var 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 });
      },
      error: function(xhr, status, err) {
        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>
    );
  }
};
like image 597
nathanhleung Avatar asked Mar 14 '23 16:03

nathanhleung


1 Answers

You need use bind(this) to bind your events. like below:

componentDidMount() {
    this.loadCommentsFromServer().bind(this);
    setInterval(this.loadCommentsFromServer.bind(this), this.props.pollInterval);
  }

You could read the reference from this link: https://facebook.github.io/react/docs/reusable-components.html#no-autobinding

No Autobinding Methods follow the same semantics as regular ES6 classes, meaning that they don't automatically bind this to the instance. You'll have to explicitly use .bind(this) or arrow functions =>.

like image 152
Ryan.Ruan Avatar answered Mar 26 '23 03:03

Ryan.Ruan