React.js Error trying to access nested data from a Json via state of the component

2

I'm starting with React.js and I'm having trouble accessing nested data in a JSON.

I am using whatwg-fetch to make the request and it is working, but I can not access the nested data of JSON, eg: data.title it displays on the screen normally, however data.container.title it accuses the error:

  

App.js: 31 Uncaught TypeError: Can not read property 'title' of undefined

I've already looked elsewhere, including the English version of stackoverflow, articles in Portuguese and English, and I have not found an answer, can anyone help me? follows the code and json accessed.

App.js

import React from 'react';
import 'whatwg-fetch';

export default class App extends React.Component {

constructor (props) {
  super(props);
  this.state = { dados:[] };
}

loadContentFromServer() {
 const url = this.props.url;

 fetch(url)
   .then(response => response.json())
   .then(json => {
     console.log(json);
     this.setState({ dados: json });
   });
}

componentDidMount() {
  this.loadContentFromServer();
}

render(){
  const data = this.state.dados;
  return (
    <div className="box">
      <h1 className="title">
        {data.container.title}<br/>
      </h1>
    </div>
  );
 }
}

Passing the Json url

index.js

ReactDOM.render(<App url="http://localhost:3232/json/content.json"/>, document.getElementById('app'));

content.json

{
  "title": "Titulo",
  "numbers": [0, 1, 2, 3],
  "container": {
    "title": "Titulo",
    "content": "conteúdo da página"
  }
}
    
asked by anonymous 16.01.2017 / 16:56

1 answer

0

You have to keep in mind that both fetch() and this.setState({ dados: json }); are asynchronous. This means that the first time React tries to render this component, the value of this.state.dados will still be an empty array as set in the constructor of the component class.

So you have to create a check for rendering not happening, ie rendering null .

Something like this:

render(){
  const data = this.state.dados;
  if (!data.container) return null;
  return (
    <div className="box">
      <h1 className="title">
        {data.container.title}<br/>
      </h1>
    </div>
  );
 }

Note:

In the constructor you start state like this: this.state = { dados:[] }; but I do not think this is what your JSON returns ..., your JSON seems to be an object. In this case it would be more correct to set state like this: this.state = { dados:{} }; .

If JSON is an array, then the constructor is semantically correct but the code in render is not. Then you need to access the array index you want. Something like this:

{data[0].container.title}<br/>
    
16.01.2017 / 17:09