Reputation: 614
I am trying to render a component that needs props passed to it. These props require data that can only come from an api fetch. The issue is that I'm fetching from the api in componentDidMount but the render method gets mounted before the componentDidMount method so it says that it cannot read property of undefined because it tries to render the component before the data gets to be fetched. heroImage is an object that gets stored into the state during the fetch call but it does not exist in the state before the fetch call.
class Home extends React.Component{
constructor(){
super();
this.state={
searchTerm: '',
movies: [],
error: false,
loading: false,
};
}
componentDidMount(){
const fetchMovies = async endpoint => {
const isLoadMore = endpoint.search('page');
try{
const result = await (await fetch(endpoint)).json();
this.setState(prev => ({
...prev,
movies: isLoadMore !== -1 ? [...prev.movies, ...result.results] : [...result.results],
heroImage: prev.heroImage || result.results[0],
currentPage: result.page,
totalPages: result.total_pages
}));
} catch(error){
alert(error);
}
}
console.log('...fetching');
fetchMovies(POPULAR_BASE_URL);
console.log('done fetching...');
}
render(){
const {heroImage} = this.state;
return(
<React.Fragment>
<HeroImage
image={`${IMAGE_BASE_URL}${BACKDROP_SIZE}${heroImage.backdrop_path}`}
title={heroImage.original_title}
text={heroImage.overview}
/>
</React.Fragment>
);
}
};
The app has trouble reading the image prop that's getting passed to the HeroImage component. This is because it requires the heroImage object that only comes from the fetch call to exist so that it can select the backdrop_path property from it. Since render method mounts first, the object is never stored in the state. This is the issue I need help solving. Thanks.
Upvotes: 0
Views: 318
Reputation: 3119
Just add an iternary check like this. So it only renders when there is data in heroImage
render(){
const {heroImage} = this.state;
return(
<React.Fragment>
heroImage && <HeroImage
image={`${IMAGE_BASE_URL}${BACKDROP_SIZE}${heroImage.backdrop_path}`}
title={heroImage.original_title}
text={heroImage.overview}
/>
</React.Fragment>
);
}
Upvotes: 1