I'm trying to dynamically set the src
attribute of my <img />
component with data fetched by axios but but constantly fail. I don't know how to get the value of urlToImage
property out of the fetched data object.
I have tried const mainArticle = articles[0].urlToImage;
and then setting the src={mainArticle}
. I can console.log(articles[0])
but not console.log(articles[0].title)
becuase it suddenly turns to undefined. Any idea why this happens?
import React, { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import AsideNews from '../../components/aside-news/aside-news.component';
import './front-page.styles.scss';
const FrontPage = () => {
const [articles, setArticles] = useState([]);
useEffect(() => {
const url =
'https://newsapi.org/v2/everything?' +
'q=guitar&' +
'from=2019-10-17&' +
'sortBy=popularity&' +
'apiKey=thisIsSecret';
const getData = async () => {
const response = await axios
.get(url)
.then(console.log('isFetched'))
.catch(err => console.error(err));
const { data } = response;
setArticles(data.articles);
};
getData();
}, []);
return (
<div className='frontpage' articles={articles}>
<main className='main-content'>
<section className='first-section'>
<AsideNews articles={articles} />
<div className='main-headline'>
<img
src={articles[0].urlToImage}
alt='main-headline'
height='400px'
width='90%'
/>
<div className='main-headline-desc'>
{articles
.filter((article, idx) => idx === 0)
.map(article => (
<p>{article.description}</p>
))}
</div>
<div className='main-headline-title'>
{articles
.filter((article, idx) => idx === 0)
.map(article => (
<Link to='/'>
<h2>{article.title}</h2>
</Link>
))}
</div>
</div>
</section>
</main>
</div>
);
};
export default FrontPage;
I expected to work the same as article.title
, but this is what I get in stead: TypeError: articles[0] is undefined
Hi you could always check if articles have been loaded before using it like this:
<img src={articles && articles[0].urlToImage} alt='main-headline' height='400px' width='90%'/>
The '&&' operator checks if it exists before trying to load it. Downside is you might have some elements of your page load while the image still remains blank.
Another option is to have an isFetched state which toggles to true when the data is loaded and you render the entire component conditionally if the data is loaded.
const[isFetched, setIsFetched] = useState(false)
const getData = async () => {
const response = await axios
.get(url)
.then(()=> {
setIsFetched(true)
//write remainder of your function
};
getData();
}, []);
return (!isFetched ? 'data loading' :
<div>Your div component</div>)