I'm coming from a Vue environment I'm a bit confused with this, I read some other question similar to this but I couldn't make it work,
why I can't echo out the value of a nested object getting from a fetch request?
I console.log
after setState
and I got the values but in the render is undefined,
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends Component {
constructor() {
super();
this.state = {
isLoading: true,
articles: {}
};
}
componentDidMount() {
this.setState({ loading: true });
fetch("./articles.json")
.then(response => response.json())
.then(result => {
this.setState({
isLoading: false,
article: result.blog.article
});
console.log(
"componentDidMount__this.state.article=",
this.state.article.link.title
); //this gets the value
})
.catch(error => {
console.error(error);
});
}
render() {
//let articleTitle;
// this gets error ----> console.log(this.state.article.link.title);
// because .link is undefined
// console.log(this.state.article);
// if (this.state.article !== "undefined") {
// console.log("wait what?..");
// if I changed the state in fetch why this stil
// articleTitle = this.state.article.link.title;
// } else {
// articleTitle = "";
// }
// I assign "this.state.article.link.title" to a variable so I can avoid the error,
//
return (
<div className="App">
{/*<h1>{articleTitle}</h1> */}
<h1>{this.state.article.link.title}</h1>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
articles.json
{
"blog": {
"article": {
"id": 1,
"title": " 1 lorem ipsum",
"description": "lorem ipsum",
"image": {
"desktop": "https://via.placeholder.com/900x500?text=desktop",
"tablet": "https://via.placeholder.com/600x400?text=tablet",
"mobile": "https://via.placeholder.com/320x320?text=mobile"
},
"link": {
"title": "lorem link",
"url": "#"
},
"author": {
"avatar": "https://via.placeholder.com/125x125?text=125x125",
"name": "lorem ipsum"
}
}
}
}
You have to put check before using dynamic states in render as it is called on both component mount and update.
This should work fine:
{this.state.isLoading ? '' : this.state.article.link.title}
It appears that this.state.article.link.title
is being referenced when this.state.article === undefined
.
The solution is to retrieve this.state.article.link.title
in a safer manner.
This is typically achieved by leveraging short-circuit evaluation . I've also used destructuring assignment and default parameters in the example below.
Assigning default values to this.state
is also recommended, especially when dealing with indeterminate data.
// Default `this.state`.
this.state = {
article: {link: {title: ''}},
articles: {},
isLoading: true,
}
// Safe retrieval of `title`.
const {article = {}} = this.state
const {link = {}} = article.link
const title = link.title || ''
TRY this
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends Component {
constructor() {
super();
}
state = {
isLoading: true,
articles: {}
};
componentDidMount() {
this.setState({ loading: true });
fetch("./articles.json")
.then(response => response.json())
.then(result => {
this.setState({
isLoading: false,
articles: result.blog.article
});
})
.catch(error => {
console.error(error);
});
}
render() {
let Test = this.state.articles ? (
<div className="App">
<h1>{this.state.articles.title}</h1>
</div>
) : null;
console.log(this.state.articles.title);
return <div>{Test}</div>;
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
It seems that render method is invoked three times before fetch method finish, so in render method this.state.articles
is empty object. You also wonders why guy from the tutorial does not have this issue, well in tutorial you mentioned object: this.state.character.name
was used and in your code this.state.articles.link.title
. This is the difference, because it is acceptable to use this.state.character.name
(it refers to property from empty object so it will return undefined, whereas your this.state.article.link.title
(it tries to access to property on object that does not exist). You can check it in console:
const obj = {};
console.log(obj.property); //undefined
console.log(obj.link.title); // Uncaught TypeError: Cannot read property 'title' of undefined
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.