我有一个像这样的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 GET
this.state.agreement
作为道具的输入,例如this.state.agreement
与我的问题有关。
从架构上讲,我希望在agreement={this.state.agreement}
级保留GET
协议,并将检索到的协议详细信息传播下来。
我错过了什么?
答案 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,以便通过好消息向您发出这些问题的警报,并为您的代码提供一些自我文档。