Reputation: 33
I have this json object which I have taken from the news API and want to print out the author of just one of the articles. I wanted to know how to do it within a react component which I have called 'author'.
Here is the json object: it's too long to include here but have the link for you to see.
It's accessible from https://newsapi.org/ and has a total of 20 articles.
I have this react component which I am trying to then print one of the article's authors:
import React, { Component } from 'react';
const APIurl = 'https://newsapi.org/v2/top-headlines?
country=it&apiKey=0b3e87958d0b4e71a9e2ed3eea69237a';
class Author extends Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
fetch(APIurl)
.then(response => response.json())
.then(response => {
this.setState({
articles: response
})
})
}
render() {
return (
<h5 class="f6 ttu tracked black-80">
{this.state.articles.article[0].author}
</h5>
);
}
}
export default Author;
However, something must not be quite right because I get this error:
TypeError: Cannot read property 'articles' of undefined
21 | render() {
22 | return (
23 | <h5 class="f6 ttu tracked black-80">
> 24 | {this.state.articles.articles[0].author}
25 | </h5>
26 | );
27 | }
I'm not sure what I have done wrong. Also sorry for the poor formating of the json object.
I've now made some changes after seeing what has been suggested below so that my code looks like this:
import React, { Component } from 'react';
const APIurl = 'https://newsapi.org/v2/top-headlines? country=it&apiKey=0b3e87958d0b4e71a9e2ed3eea69237a';
class Author extends Component {
constructor(props) {
super(props);
this.state = {
articles: []
};
}
componentDidMount() {
fetch(APIurl)
.then(response => response.json())
.then(response => {
this.setState({
articles: response
})
})
}
render() {
const { articles } = this.state;
return (
<h5 class="f6 ttu tracked black-80">
{articles.length>0 && articles.articles[1].author}
</h5>
);
}
}
export default Author;
However, it still doesn't print out anything in the author react component even though when I go to the chrome developer tools and see the state of the component it looks like this:
State
articles: {…}
articles: Array[20]
0: {…}
1: {…}
author: "Davide Stoppini"
description: "A Pisa, divertente pareggio con i russi, più avanti per quanto riguarda la condizione fisica. Passi in avanti rispetto al Sion: bene gli esterni offensivi, anche i due attaccanti confermano la confide…"
publishedAt: "2018-07-21T20:20:21Z"
source: {…}
title: "Inter, fuochi d'artificio con lo Zenit: è 3-3. In gol Icardi e Lautaro"
url: "https://www.gazzetta.it/Calcio/Serie-A/Inter/21-07-2018/inter-fuochi-d-artificio-lo-zenit-3-3-gol-icardi-lautaro-280799153444.shtml"
urlToImage:"https://images2.gazzettaobjects.it/methode_image/2018/07/21/Calcio/Foto%20Calcio%20-%20Trattate/1d50f03c94d965c2ca84bd3eec0137c9_169_xl.jpg
*Note: this is only showing the first second element of the articles array.
Upvotes: 1
Views: 6969
Reputation: 189
News App in React Native:
const SITE_URL =
"https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=a39bbc7131c649a3ad23fe79063d996f";
const TestScreen = () => {
const [myData, setMyData] = useState();
useEffect(() => {
axios
.get(SITE_URL)
.then((res) => {
// console.log("Response from main API: ", res);
console.log(
"----------------------------------------------------------- Start"
);
// console.log("Response from Home Data Data: ", res.data.data);
console.log(
"Response from NEWS data articles: ",
res.data.articles
);
console.log(
"----------------------------------------------------------- End"
);
// let companyData = res.data.data;
let companyData = res.data.articles;
setMyData(companyData);
setData({
Company: companyData,
Description: "",
});
})
.catch((err) => {
console.log(err);
});
}, []);
// console.log("myData:", { myData });
const renderItem = ({ item, index }) => (
<TouchableOpacity style={styles.container}>
<Text style={styles.title}>
{index}. {item.author}
</Text>
<Text> {item.description} </Text>
<View>
<Image
style={{
width: 500,
height: 100,
}}
source={{
uri: item.urlToImage,
}}
/>
</View>
</TouchableOpacity>
);
return (
<View style={styles.container}>
<Text>Read Later Screen</Text>
<Text>|</Text>
{<FlatList data={myData} renderItem={renderItem} />}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
export default TestScreen;
Upvotes: 0
Reputation: 2870
Basically, you have to declare articles as empty array initially as follows:
this.state = {
articles: []
};
And also need to modify your code inside render as follows:
{this.state.articles && (this.state.articles.article.length>0) &&
this.state.articles.article[0].author
}
Hope it will help you.
Upvotes: 1
Reputation: 5838
The problem you are having is because your code is not prepared to go through the lifecycle of React. Before you get the data in the componentDidMount
phase there is a render phase, that is where the error is happening. In that render phase articles
should be an empty array without data and then you need a check to avoid rendering any stuff if the array is empty. So to avoid to have that error in the render
phase before the componentDidMount
phase you need to set in state an empty array called articles
, and in the render method to check if it is not empty, to render the value you want.
import React, { Component } from 'react';
const APIurl = 'https://newsapi.org/v2/top-headlines?
country=it&apiKey=0b3e87958d0b4e71a9e2ed3eea69237a';
class Author extends Component {
constructor(props) {
super(props);
this.state = { articles: []};
}
componentDidMount() {
fetch(APIurl)
.then(response => response.json())
.then(response => {
this.setState({
articles: response.articles
})
})
}
render() {
const { articles } = this.state;
return (
<h5 class="f6 ttu tracked black-80">
{articles.length > 0 && articles[0].author}
</h5>
);
}
}
export default Author;
Upvotes: 0