javascript - 尝试作为 Prop 传递时, react 状态变量意外未定义

标签 javascript reactjs

我有一个像这样的 React 组件层次结构:

 AgreementContentWidget
   AgreementTitleContainer
     AgreementTitle <-- this is ok, but
     CommentList    <-- problem here
   SectionsContainer

安装AgreementContentWidget :

 <AgreementContentWidget agreement_id={85} />

请求小部件加载协议(protocol) 85。

var AgreementContentWidget = React.createClass({
  getInitialState: function() {
    return {agreement: []};
  },

  componentWillMount: function() {
    this.loadAgreementDetails();
  },

  loadAgreementDetails: function() {
    $.ajax({
      url: "/agreements/" + this.props.agreement_id, 
      type: 'GET',
      dataType: 'json',
      success: function(agreement) {
        this.setState({agreement: agreement.agreement});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error("/agreements/" + this.props.agreement_id, status, err.toString());
      }.bind(this)
    });
  },

  handleAgreementUpdate: function() {
    this.loadAgreementDetails();
  },

  render: function() {
    return (
      <div className="panel panel-default">
        <div className="panel-body" id={"container_agreement_" + this.state.agreement.id}>
          <div className="col-lg-12">           
            <AgreementTitleContainer agreement={this.state.agreement} onAgreementUpdate={this.handleAgreementUpdate} />
            <SectionsContainer agreement={this.state.agreement} />
          </div>
        </div>
      </div>
    );
  }
});

我通过 agreement={this.state.agreement}<AgreementTitleContainer>呈现包含协议(protocol)标题的组件。

内部<AgreementTitleContainer> :

var AgreementTitleContainer = React.createClass({
  handleAgreementUpdate: function() {
    this.props.onAgreementUpdate();
  },

  render: function() {
    return (
      <div className="row" id="container_title">
        <AgreementTitle agreement={this.props.agreement} onAgreementUpdate={this.handleAgreementUpdate} />
        <CommentList commentable_type={"agreement"} commentable_id={this.props.agreement.id} />
        <br />
      </div>
    );
  }
});

<AgreementTitle>需要 {this.props.agreement}它有协议(protocol) 85 的内容。它按预期呈现并执行其他操作。 然而,<CommentList>undefined对于 commentable_id作为this.props.agreement.id未定义(通过调试器:this.props.agreement 对于此组件始终未定义)。

所以:

  • 为什么是{this.props.agreement}<AgreementTitle> 定义?
  • 为什么未定义 <CommentList>

我知道 <CommentList>在将值传递给 commentable_id 的其他上下文中按预期工作(例如 commentable_id={42} )而不是来自 this.state 中的对象(如上所述)。

我注意到 <CommentList>当它尝试 GET 时在 loadComments() 中请求下面:

var CommentList = React.createClass({
  getInitialState: function() {
    return {comments: []};
  },

  componentDidMount: function() {
    this.loadComments();
  },

  loadComments: function() {
    $.ajax({
      url: "/comments/?commentable_type=" + this.props.commentable_type + "&id=" + this.props.commentable_id, 
      type: 'GET',
      dataType: 'json',
      success: function(comments) {
        this.setState({comments: comments.comments});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error("/comments/?commentable_type=" + this.props.commentable_type + "&id=" + this.props.commentable_id, status, err.toString());
      }.bind(this)
    });
  },
  ...
  ...
}

我从失败 GET 收到一条错误消息

GET https://tinya-thedanielmay-2.c9.io/comments/?commentable_type=agreement&id=undefined 404 Not Found

如我所料,id (来自 this.props.commentable_id 以上)是 undefined .然而,console.error函数然后打印出:

/comments/?commentable_type=agreement&id=85 error Not Found

所以在那个执行点,this.props.commentable_id现在似乎已经定义好了。

我认为 <AgreementContentWidget> 的决定到:

  • GET同意 85
  • 设置this.state.agreement同意 85 详细信息 <--
  • 然后继续使用this.state.agreement作为 Prop 的输入,例如agreement={this.state.agreement}

与我的问题有关。

在架构上,我想保留 GET协议(protocol) <AgreementContentWidget>级别并让检索到的协议(protocol)详细信息向下传播。

我错过了什么?

最佳答案

您在 getInitialState 中初始化的内容第一次通过的是什么<AgreementContentWidget>渲染。你觉得<AgreementTitle>工作正常,因为当您从后端获取协议(protocol)数据时它会重新呈现,但是 CommentsList 依赖于该 ID 来加载它自己的数据,在它可以呈现之前会出错。它不知道出去再次获取数据,因为它只在 componentDidMount 中加载。 .

您应该推迟对评论的检索,直到获得正确的属性。为此,请使用 React 的 componentWillReceiveProps(nextProps)功能并等到agreement.id存在,并且在加载 ajax 之前不为 0。

所以删除 this.componentDidMount来自 CommentList 并添加:

this.componentWillReceiveProps(nextProps){
  if(nextProps.agreement && nextProps.agreement.id){
    this.loadComments();
  }
}

您还应该设置 propTypes,这样您就可以通过友好的消息提醒您注意这些问题,并为您的代码提供一些 self 文档。

关于javascript - 尝试作为 Prop 传递时, react 状态变量意外未定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30635283/

相关文章:

reactjs - 导入 "TypeError: Cannot read property ' 包时出现错误 "React-Magnific-Popup"object' of undefined"

javascript - 从 json 对象打印选定的属性

javascript - 将不同的列表项添加到无序列表数组

php - 检索带有偏移值的选定文本

javascript - 那么如何将数据推送到 promise 中的数组呢?

javascript - ReactJS 中的路由。 URL已显示,但组件未呈现

iOS 版本构建崩溃 : TypeError: n. 渲染不是一个函数。 (在 'n.render()' 中, 'n.render' 未定义)React Native 0.56

reactjs - axios GET请求函数在react中导出/导入

node.js - 为未经授权的用户模糊照片

javascript - iframe 中的视口(viewport)元标记