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:

  • get agreement 85
  • set this.state.agreement agreement 85 details <--
  • then proceed use this.state.agreement input 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

Popular posts from this blog

Magento/PHP - Get phones on all members in a customer group -

php - .htaccess mod_rewrite for dynamic url which has domain names -

Website Login Issue developed in magento -