I'm trying to map an array of movies which I get from an api. The data is fetched successfully but when I try to map the values and display, it becomes undefined and does not show anything. I'm new to react so any help and advice would be helpful.
const[items, setItems] = useState([]);
const getMovieData = ()=> {
axios.get(api_url)
.then( (response) => {
const allMovies = response.data;
console.log(allMovies);
setItems(allMovies);
}).catch( error => console.error(`Error: ${error}`));
};
useEffect(()=>{
getMovieData();
}, []);
return (
<div>
{items.map( (item)=>{
<p>{item.title}</p>
})}
</div>
);
The data is stored like this
0: {adult: false, backdrop_path: '/9eAn20y26wtB3aet7w9lHjuSgZ3.jpg', id: 507086, title: 'Jurassic World Dominion', original_language: 'en', …}
CodePudding user response:
You're not returning anything from your map
{items.map( (item)=>{
// Add a return
return <p>{item.title}</p>
})}
CodePudding user response:
First, your items value is an empty array[]
as you have initialized with setState([])
and your useEffect()
runs only after your component is rendered which means even before you could do your data fetching, your HTML is being displayed inside which you are trying to get {item.title}
where your items is an empty array currently and hence undefined. You will face this issue often as you learn along. So if you want to populate paragraph tag with item.title
you should fast check if your items is an empty array or not and only after that you can do the mapping as follow and also you need to return the element from the map callback. If it takes some time to fetch the data, you can choose to display a loading indicator as well.
const [items, setItems] = useState([]);
const getMovieData = () => {
axios.get(api_url)
.then((response) => {
const allMovies = response.data;
console.log(allMovies);
setItems(allMovies);
}).catch(error => console.error(`Error: ${error}`));
};
useEffect(() => {
getMovieData();
}, []);
return ( < div > {
items.length !== 0 ? items.map((item) => {
return <p > {
item.title
} < /p>
}) : < LoadingComponent / >
}
<
/div>
);
CodePudding user response:
Good catch by Ryan Zeelie, I did not see it.
Another thing, since you're using promises and waiting for data to retrieve, a good practice is to check if data is present before mapping.
Something like :
return (
<div>
{ (items.length === 0) ? <p>Loading...</p> : items.map( (item)=>{
<p>{item.title}</p>
})}
</div>
);
Basically, if the array is empty (data is not retrieved or data is empty), display a loading instead of mapping the empty array.