2016-03-31 2 views
1

На моем пути к обучению React и ES6 я взял официальный учебник и поиграл, чтобы сделать его совместимым с ES6. Но когда дело доходит до выполнения запроса Ajax, я получаю следующее сообщение об ошибке:Почему this.props undefined в моем коде ReactJS?

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

Вот мой CommentBox файл/код:

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; кажется, не знает, что такое this.props. Я думал, что это была эта ссылка проблема и нашел similar question, где для устранения проблемы предлагается использовать новые стрелки ES6. Затем я попробовал: loadCommentsFromServer =() => {}, но Browserify жалуется и не строит.

+0

Возможный дубликат [Как получить доступ к правильному \ 'this \'/context внутри обратного вызова?] (Http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context -indide-a-callback) –

+0

См. «Общая проблема: использование объектных методов в качестве обратных вызовов/обработчиков событий» в предлагаемом дубликате. –

+0

Вам необходимо связать его вручную. ES6 класс не autobind – thangngoc89

ответ

6

Эта линия ваша проблема:

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

Вы передаете метод loadCommentsFromServer к setInterval, но это будет вызываться без контекста поэтому this больше не будет связан с вашим компонентом (this будет привязан к окну). Вместо этого вы должны сделать что-то вроде этого:

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

Наконец, следует сохранить интервал идентификатор, так что вы можете очистить его, когда ваш компонент демонтирована:

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, и вы сможете это сделать, и он решит вашу проблему без необходимости вручную bind или оберните ваш обратный вызов в новой функции стрелки жира, когда вы позвоните setInterval.

Смежные вопросы