【问题标题】:Why is this.props undefined in my ReactJS code?为什么我的 ReactJS 代码中未定义 this.props?
【发布时间】:2016-03-31 15:26:05
【问题描述】:

在学习 React 和 ES6 的过程中,我学习了官方教程并尝试使其与 ES6 兼容。但是在执行 Ajax 请求时,出现以下错误:

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

这是我的评论框文件/代码:

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 是什么。我认为这是一个 this reference 问题,并找到了 similar question 建议使用新的 ES6 箭头来解决问题。然后我尝试了:loadCommentsFromServer = () =&gt; {},但是 Browserify 抱怨并且没有构建。

【问题讨论】:

标签: reactjs ecmascript-6


【解决方案1】:

这一行是你的问题:

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

最后,你应该存储间隔id,以便在卸载组件时清除它:

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

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

【讨论】:

  • 谢谢!这就是问题所在,解释也很清楚
  • 如果您使用类属性并将loadCommentsFromServer 定义为箭头函数,您实际上不需要在setInterval 处更改这些代码。
  • @Aaron 我个人不建议在 SO 上使用非常早期的语言功能(除非问题是专门针对它们的)。它增加了解决问题的复杂性,如果功能没有标准化,那么未来的答案将变得毫无用处
【解决方案2】:

我认为这是一个参考问题,我在谷歌上搜索发现 一个类似的 stackoverflow 问题,他们建议使用新的 ES6 箭头来解决问题。然后我尝试使用:loadCommentsFromServer = () =&gt; {} 但 browserify 抱怨并且不构建:/

ES6 箭头函数确实可以解决您的问题。构建错误是因为 ES6 不支持类属性,而loadCommentsFromServer = 是类属性初始化器。启用ES7 class properties,您应该能够做到这一点,它将解决您的问题,而无需手动bind 或在您调用setInterval 时将回调包装在新的粗箭头函数中。

【讨论】:

    猜你喜欢
    • 2019-03-22
    • 2015-04-11
    • 2018-12-14
    • 2016-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-19
    • 1970-01-01
    相关资源
    最近更新 更多