Reputation: 91
how to I get the property of an array of objects in the render function. if I try this:
render() {
console.log(this.state.items[0].name);
(...)
I got an error:
TypeError: this.state.items[0] is undefined
class App extends React.Component {
constructor() {
super()
this.state = {
items: []
}
}
componentWillMount() {
fetch('http://swapi.co/api/people/?format=json')
.then((response) => response.json())
.then(({ results: items }) => this.setState({ items }))
}
filter(e){
this.setState({ filter: e.target.value })
console.log(this.state.items[0].name);
}
render() {
console.log(this.state.items[0].name);
return (
<div>
<input type="text" onChange={this.filter.bind(this)} />
</div>
)
}
}
export default App
However, if I log out only the first element of the array
console.log(this.state.items[0])
it prints out the object
Object { name: "Luke Skywalker", height: "172", mass: "77", hair_color: "blond", skin_color: "fair", eye_color: "blue", birth_year: "19BBY", gender: "male", homeworld: "http://swapi.co/api/planets/1/", films: Array[5], 6 more… }
When the filter function get fired I do get the property of the first element console.log(this.state.items[0].name)
prints out:
Luke Skywalker
What's happening here?
Upvotes: 2
Views: 3041
Reputation: 104529
fetch
is asynchronous call, so during first time rendering this.state.items
will []
and you are trying to access the name
of 0th item that doesn't exist, and it is throwing the error because of that.
When you are using:
console.log(this.state.items);
Check the console it was printing two values one []
and another one will be the data that you are getting from server.
Solution:
Put the check on length inside render it will print the proper name once you get the response.
Like this:
render(){
if(this.state.items.length)
console.log(this.state.items[0].name);
return(
....
)
}
Upvotes: 1
Reputation: 811
Your state.items array is not set until your fetch has completed. Your render method will be called prior to this, therefore, it won't work as expected.
If you recheck your console output, I have a feeling you'll see some nulls or undefined's prior to the your object showing.
Try this:
render() {
console.log(this.state.items.length > 0 ? this.state.items[0].name : 'Items not loaded yet');
return (
<div>
<input type="text" onChange={this.filter.bind(this)} />
</div>
)
}
Upvotes: 2