React.js Error trying to access nested Json data via component state

Asked

Viewed 756 times

2

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

I’m using the whatwg-fetch to make the request and it’s working, but I can’t access the nested JSON data, example: data.title it displays on the screen normally though data.container.title he accuses the error:

App.js:31 Uncaught Typeerror: Cannot read Property 'title' of Undefined

I have looked elsewhere including in the English version of stackoverflow, articles in Portuguese and English and I did not find an answer, can anyone help me? follows the code and the 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"
  }
}
  • React already calls the render before you make the request on didMount and receive the result. Before the request occurs, there is no data.container.title, so I think that’s the problem. So try to start data.container.title with some other information before

1 answer

0


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

So you have to create a check to make it not happen, ie render null.

Something like that:

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 the state thus: this.state = { dados:[] }; but I don’t think that’s what your JSON returns..., your JSON seems to be an object. In this case it would be more correct to set the state thus: this.state = { dados:{} };.

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

{data[0].container.title}<br/>
  • Thank you @Sergio, it worked perfectly, but I still don’t understand why it can access the first level of JSON as if it had partially loaded the data, and actually the this.state = { dados:[] } was wrong, I corrected for this.state = { dados: {} }

  • @Leandrom.Silva great to have worked! You can explain better "can access the first level of JSON"? where do you think it happens?

  • sorry for the delay in responding, so I realized that when I accessed dados.title in my application it returned the correct value, however, when I tried to access dados.container.title or dados.container.content console accuses error of Undefined! tried to replicate the error by jsFiddle to be clearer but could not!

  • @Leandrom.Silva You can put here what appears on the console with .then(response => console.log(typeof response, response))?

Browser other questions tagged

You are not signed in. Login or sign up in order to post.