尝试传递为道具时,意外地反应状态变量未定义

时间:2015-06-04 05:03:08

标签: javascript reactjs

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

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

挂载{{​​1}}:

AgreementContentWidget

请求小部件加载协议85。

 <AgreementContentWidget agreement_id={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>

<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>并且它已获得协议85的内容。它按预期呈现并执行其他操作。 但是,{this.props.agreement} <CommentList> undefined commentable_id未定义<{1}} (通过调试器:this.props.agreement.id始终未定义此组件)

所以:

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

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

我注意到this.state在下面的<CommentList>中尝试GET请求时发现{/ 1}}:

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>协议85
  • 使用协议85详细信息&lt; -
  • 设置GET
  • 然后继续使用this.state.agreement作为道具的输入,例如this.state.agreement

与我的问题有关。

从架构上讲,我希望在agreement={this.state.agreement}级保留GET协议,并将检索到的协议详细信息传播下来。

我错过了什么?

1 个答案:

答案 0 :(得分:4)

您在getInitialState初始化的内容是第一次<AgreementContentWidget>呈现的内容。您认为<AgreementTitle>正常工作,因为当您从后端获取协议数据时它会被重新呈现,但是依赖于该ID来加载其自己的数据的CommentsList将在它呈现之前发生错误。它不知道出去再次获取数据,因为它只在componentDidMount中加载。

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

从评论列表中删除this.componentDidMount并添加:

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

您还应该设置propTypes,以便通过好消息向您发出这些问题的警报,并为您的代码提供一些自我文档。