I know why I am getting the error but I can’t find a solution at the moment. Context:
I am fetching data to my app using async await
operation. Let’s assume the data looks like this:
{
id: string,
title: string,
genres: array // Array of objects
}
// genres object
[
{ name: string }, {name: string }
]
// Code
class App extends Component {
state = {
movies: []
}
async componentDidMount() {
const { data: movies } = await Axios.get(apiEndpoint)
this.setState({ data })
}
render() {
return {this.state.movies.map(m => <p>m.genres[0].name</p>)}
}
This would throw the following error: TypeError: Cannot read property ‘genres’ of undefined
I know this is happening because the render
method can’t wait for CDM so render
will call the state with its default value at least once. How can I solve this?
A couple things.
const { data: movies } = await Axios.get(apiEndpoint)
You are getting back an object and you are pulling out a property called data and changing it’s name to movies. OK. But on the next line:
this.setState({ data })
you are trying to set the variable data onto the state property data. There is not variable data and there is no state property data. I think you want:
this.setState({ movies })
Then:
return {this.state.movies.map(m => <p>m.genres[0].name</p>)}
Don’t you need to escape that JS?
<p>{m.genres[0].name}</p>
OK. But I don’t get why m is undefined. Even if this.state.movies is just an empty array, it should just skip over it. It’s like there is and array but it doesn’t contain what you think it does.
Whenever I get confused, I start console.log
ging things. Like:
async componentDidMount() {
const { data: movies } = await Axios.get(apiEndpoint)
this.setState({ movies }, () => console.log('after setState', this.state))
}
render() {
console.log('render, this.state', this.state);
return {this.state.movies.map(m => {
console.log('in map, m is', m)
return <p>{ m.genres[0].name }</p>)
}
}
When in doubt, just see what you’re getting.