javascript - React state variable unexpectedly undefined when trying to pass as props -
i have react component hierarchy this:
agreementcontentwidget agreementtitlecontainer agreementtitle <-- ok, commentlist <-- problem here sectionscontainer mounting agreementcontentwidget:
<agreementcontentwidget agreement_id={85} /> requests widget load agreement 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> ); } }); i pass agreement={this.state.agreement} <agreementtitlecontainer> render components comprising agreement's title.
inside <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> takes {this.props.agreement} , it's got contents of agreement 85. renders , other operations expected. however, <commentlist> has undefined commentable_id this.props.agreement.id undefined (via debugger: this.props.agreement undefined component).
so:
- why
{this.props.agreement}defined<agreementtitle>? - why undefined
<commentlist>?
i know <commentlist> works expected in other contexts value passed commentable_id (e.g. commentable_id={42}) rather object in this.state (as above).
i noted <commentlist> when tries get request in loadcomments() below:
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) }); }, ... ... } i error message failed get
get https://tinya-thedanielmay-2.c9.io/comments/?commentable_type=agreement&id=undefined 404 not found which expect, id (from this.props.commentable_id above) undefined. however, console.error function prints out:
/comments/?commentable_type=agreement&id=85 error not found so @ point of execution, this.props.commentable_id seems defined now.
i'm thinking decision <agreementcontentwidget> to:
getagreement 85- set
this.state.agreementagreement 85 details <-- - then proceed use
this.state.agreementinput props, e.g.agreement={this.state.agreement}
has issues.
architecturally, i'd retain get agreement @ <agreementcontentwidget> level , have retrieved agreement details propagate down.
what missing?
what you're initializing in getinitialstate what's passed first time <agreementcontentwidget> renders. think <agreementtitle> works because re-rendered when agreement data backend, commentslist, being dependent on id load own data, error out before can render. doesn't know go out , data again because it's loading in componentdidmount.
you should defer retrieval of comments until correct property. this, use react's componentwillreceiveprops(nextprops) function , wait until agreement.id exists, , not 0 before loading ajax.
so remove this.componentdidmount commentlist , add this:
this.componentwillreceiveprops(nextprops){ if(nextprops.agreement && nextprops.agreement.id){ this.loadcomments(); } } you should set proptypes can alerted these issues nice messages , provide self documentation code.
Comments
Post a Comment