I'm following the reactjs
tutorial, and I keep running into an issue when
passing the value from the state of one component into another component.
The error Cannot read property 'map' of undefined'
is thrown when the map
function in the CommentList
component is executed.
What would cause the
prop
to beundefined
when passing fromCommentBox
into theCommentList
?
// First component
var CommentList = React.createClass({
render: function() {
var commentNodes = this.props.data.map(function (comment){
return <div><h1>{comment.author}</h1></div>;
});
return <div className="commentList">{commentNodes}</div>;
}
});
// Second component
var CommentBox = React.createClass({
getInitialState: function(){
return {data: []};
},
getComments: function(){
$.ajax({
url: this.props.url,
dataType: 'json',
success: function(data){ this.setState({data: data}) }.bind(this),
error: function(xhr, status, err){ console.error(url, status, err.toString()) }.bind(this)
});
},
componentWillMount: function(){
this.getComments()
},
render: function(){
return <div className="commentBox">{<CommentList data={this.state.data.comments}/>}</div>;
}
});
React.renderComponent( <CommentBox url="comments.json" />, document.getElementById('content'));
First of all, set more safe initial data:
getInitialState : function() {
return {data: {comments:[]}};
},
And ensure your ajax data.
It should work if you follow above two instructions like Demo.
Updated: you can just wrap the .map block with conditional statement.
if (this.props.data) {
var commentNodes = this.props.data.map(function (comment){
return (
<div>
<h1>{comment.author}</h1>
</div>
);
});
}
This solution worked, but I'm curious. If I have a more complicated JSON structure, would I have to initialize the data object the same way? It seems like there should be a better way. Thanks
@Nael No, you don't need to. Just wrap the block like above. :)
The error occurs because
this.props.data
is null..map
expects to be called on an array.@timothyclifford thanks for the answer. I understand
this.props.data
is null which caused the map function to fail. But what I don't understand is that the tutorial code works without the if clause. Whythis.props.data
is not null in the tutorial?this.props.data
is populated by the AJAX request. The AJAX is asynchronous so if the component is rendered before the data is populated,this.props.data
will be null and you'll get the error. Does this make sense?