DigitalDisaster DigitalDisaster - 2 months ago 5
React JSX Question

React render is choking on nested object in property

I have this react component. It is passed a prop called data.

data is an object like

{
"title" : "some title",
"meta" : { "name": "frank",
"last": "lee"
}
}



export default class Details extends React.Component {

constructor () {
super()

this.state = {
data: []
}
}

render () {
return (
<div>
<h1>{this.props.data.title}</h1>
</div>
)
}
};


This renders fine. Howerever when I try to reference the nested object included in this prop the whole prop becomes "undefined" and I cannot reference anything.

Full Error:

Uncaught TypeError: Cannot read property 'name' of undefined


This breaks:

render () {
return (
<div>
<h1>{this.props.data.title}</h1>
<p>{this.props.data.meta.name}</p>
</div>
)
}


This breaks:

render () {

var name = this.props.data.meta.name

return (
<div>
<h1>{this.props.data.title}</h1>
<p>{name}</p>
</div>
)
}


everything breaks. I'm sure it's something small that i'm overlooking and some extra eyes might help me out here.

edit:

This is the Component calling Details.jsx

import Details from './Details.jsx'

export default class DetailsWrap extends React.Component{
constructor () {
super()

this.state = {
data: []
}
}

loadData = (id) => {
apipromise.getDetails(id)
.success((response) => {

this.setState({
data: response
})

})
.fail((response) => {

});
}

componentDidMount () {

this.loadData(this.props.id)
}

render () {

return (
<Details data={this.state.data}/>
)
}

};

Answer

It looks as though data is not necessarily set before render fires. Since you set an initial (empty) data property, when you call this.props.data.title on the initial render, the value is null but it doesn't blow up because the object is sufficiently shallow. However, calling name on an empty meta property blows up, because meta doesn't exist.

You've set loadData to use a promise, but that promise doesn't prevent the initial render of the component, where the error is occurring. Your best bet is to either render nothing until this.props.data.meta has a value, or else hedge your name variable, eg.

const name = this.props.data.meta && this.props.data.meta.name;

This will likely still flash undefined, though it won't blow up.