const [loading, setLoading] = useState(false);
const [meal, setMeal] = useState([]);
useEffect(() => {
setLoading(true);
async function fetchData() {
const response = await axios.get('/random.php');
setMeal(response.data.meals);
setLoading(false);
return response;
}
fetchData();
}, []);
return (
<Card className={classes.Root}>
<CardActionArea>
<CardMedia className={classes.Media} title="food">
<img src={meal[0].strMealThumb} alt="cat" />
</CardMedia>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{meal[0].strMeal}
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
{meal[0].strInstructions}
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<Button size="small" color="primary">
Learn More
</Button>
</CardActions>
</Card>
);
I'm using the coed above but I get an error TypeError: Cannot read property 'strMealThumb' of undefined. I tried multiple ways with useEffect and still have the same issue
When your component renders for the first time, the network request to /random.php
hasn't happened yet, so meal
is set to its default value ([]
). You're attempting to set the image source to meal[0].strMealThumb
, but meal
is an empty array, so meal[0]
returns undefined
, and you see the error you posted.
The solution is to prevent the component body from rendering while meal
is loading, and when meal
is an empty array (in case /random.php
returns an empty array).
meal
is an array, so you should name it meals
instead.
const MyComponent = () => {
const [loading, setLoading] = useState(false);
const [meals, setMeals] = useState([]);
if (loading) {
return (
<div>Loading...</div>
);
}
if (meals.length === 0) {
return (
<div>No meals found!</div>
);
}
return ( /* ... */ );
};