Reputation: 47
I'm trying to render a nested JSON in react but I receive the error "TypeError: Cannot convert undefined or null to object" when I try to render the nested parts. Those parts are converted to objects when are stored in the state of the component by the componentDidMount() method, so I'm trying to use Object.keys() function. For expample, in the next JSON:
{
"gear": 14,
"valid": 1,
"meteo": {
"wind_direction": 152,
"wind_velocity": 10.1
},
}
When I try to render it using the Object.keys() function, like this:
const haul = this.state.haul
{Object.keys(haul.meteo).map( key => {
return(<p>Sea state: {haul.meteo[key]} </p>)
})}
the error is thrown in the Object.keys() line, and I don't understand why.
The complete component is this:
class ComponentsHaul extends Component {
constructor(props) {
super(props);
this.state = {
haul: []
};
this.apiHaul = "http://myapi";
}
componentDidMount() {
fetch(this.apiHaul)
.then(response => {
return response.json();
})
.then(haul => {
this.setState(() => {
return {
haul
};
});
});
}
render() {
const haul = this.state.haul
return (
<Fragment>
<p>Gear: {haul.gear}</p>
{Object.keys(haul.meteo).map( key => {
return(<p>Sea state: {haul.meteo[key]} </p>)
})}
</Fragment>
);
}
}
Upvotes: 1
Views: 190
Reputation: 203257
haul
is initially an array, there is no meteo
, so Object.keys(haul.meteo)
fails. You then later change the type (a no-no) to an object, keep the type consistent.
const state = { haul: [] };
console.log(Object.keys(state.haul.meteo));
If you change your initial state to provide an empty meteo
object this should work for you on initial and subsequent renders while data is fetched.
this.state = {
haul: {
meteo: {},
},
}
const state = { haul: { meteo: {} } };
console.log(Object.keys(state.haul.meteo));
Upvotes: 1
Reputation: 3285
This issue is coming on first render.
See, haul is state containing empty array []. When it renders first time, React tries to access meteo at line
Object.keys(haul.meteo)
But haul has no property named meteo which is undefined. Thus, React reads it like
Object.keys(undefined)
And you are getting this error. (componentDidMount runs after 1st render)
Solution: Instead check existence of meteo first, like this.
{
haul.meteo ? Object.keys(haul.meteo).map( key => {
return(<p>Sea state: {haul.meteo[key]} </p>)
})} : []
}
Upvotes: 0
Reputation: 477
You should first check if your haul
state has meteo
. When the component rendered your fetch data will not be ready yet. So, it is not safe to use property that doesn't exist yet.
render() {
const haul = this.state.haul;
if(!haul.meteo) {
return <p>Loading...</p>
}
return (
<Fragment>
<p>Gear: {haul.gear}</p>
{Object.keys(haul.meteo).map((key) => {
return <p key={key}>Sea state: {haul.meteo[key]} </p>;
})}
</Fragment>
);
}
And, of course, don't forget to add key
prop while rendering array of React children.
Upvotes: 0
Reputation: 2114
This is because when you first render the component your state is empty.
Just add a condition:
{ hulu.meteo.length > 0 && Object.keys(haul.meteo).map( key => {
return(<p>Sea state: {haul.meteo[key]} </p>)
})}
Upvotes: 0