2016-03-31 17 views
1

私はReactとES6を学びました。私は公式のチュートリアルをとり、ES6と互換性を持たせるために遊びました。しかし、それはAjaxリクエストを実行することになると、私は次のエラーを取得する:ReactJSコードでthis.propsが定義されていないのはなぜですか?

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> 
    ); 
    } 
} 

エラーがloadCommentsFromServerに起こる;:

CommentBox.js:23 Uncaught TypeError: Cannot read property 'url' of undefined

ここに私のCommentBoxファイル/コードがありますthis.propsが何であるかわからないようです。私はそれがこの参照の問題だと思って、similar questionを見つけました。問題を解決するために新しいES6の矢印を使用することをお勧めします。私はその後試しました:loadCommentsFromServer =() => {}、しかし、Browserifyは文句を言ってビルドしません。

+0

[コールバック内の正しい\ 'this \' /コンテキストにアクセスするにはどうすればいいですか?](http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context -inside-a-callback) –

+0

「共通の問題:コールバック/イベントハンドラとしてのオブジェクトメソッドの使用」を参照してください。 –

+0

手動でバインドする必要があります。 ES6クラスはオートバイではありません – thangngoc89

答えて

6

この行はあなたの問題です:

setInterval(this.loadCommentsFromServer, this.props.pollInterval); 

thisはウィンドウにバインドされますあなたがsetIntervalにメソッドloadCommentsFromServerを渡していませんが、それは文脈なしで起動されますのでthisは、もはやあなたのコンポーネントにバインドします)。代わりに、このような何かを行う必要があります:あなたのコンポーネントがアンマウントされたときに、あなたがそれをクリアすることができるように

setInterval(this.loadCommentsFromServer.bind(this), this.props.pollInterval); 
// OR... use a fat arrow, which preserves `this` context 
setInterval(() => this.loadCommentsFromServer(), this.props.pollInterval); 

最後に、あなたは、インターバルIDを保存する必要があります。

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

componentWillUnmount() { 
    clearInterval(this.intervalId); 
} 
+0

ありがとう!これは問題であり、非常に明確な説明でもあります –

+0

クラスプロパティを使用して矢印関数として 'loadCommentsFromServer'を定義すると、実際には' setInterval'でこれらのコード変更のいずれかが必要なくなります。 – Aaron

+0

@Aaron個人的に私は非常に初期段階の言語機能をSOにはお勧めしません。それは問題を解決する上で複雑さを増し、機能が標準化されなければ、将来答えは無用になります – WickyNilliams

1

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矢印機能でしょう確かにあなたの問題を解決する。ビルドエラーは、ES6がクラスプロパティをサポートしておらず、loadCommentsFromServer =がクラスプロパティ初期化子であるためです。 ES7 class propertiesを有効にしてください。これを行うことができるはずです。setIntervalを呼び出すと、手動でbindを必要とせずに問題を解決したり、新しい太い矢印の機能でコールバックをラップしたりします。

関連する問題