我有一个像这样的 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/