Reputation: 27
Relatively new to React, wrote a few components before (successfully), but this is the first time I'm getting something started from scratch. I use Rails with Cassandra to provide JSON responses, and everything on the back end side is working fine.
My data this.state.data
looks like this:
0 {id: {n: 2.1751612473052575e+38}, email: "[email protected]", high_score: 73, shoe_size: 10.5, updated_at: "2018-11-06T01:23:36.611-08:00"}
1 {id: {n: 2.8024982600468778e+38}, email: "[email protected]", high_score: 13, shoe_size: 7.5, updated_at: "2018-11-06T01:24:55.791-08:00"}
2 {id: {n: 2.4227336868283995e+38}, email: "[email protected]", high_score: 99, shoe_size: 10.5, updated_at: "2018-11-06T01:24:07.858-08:00"}
And doing this.state.data[1]
obviously returns
{id: {n: 2.8024982600468778e+38}, email: "[email protected]", high_score: 13, shoe_size: 7.5, updated_at: "2018-11-06T01:24:55.791-08:00"}
However, this.state.data[1].email
throws this
TypeError: undefined is not an object (evaluating 'this.state.data[1].email')
What can I do to access email and the rest of the data?
full component code:
import React, { Component } from 'react';
export default class Table extends Component {
constructor() {
super();
this.state = {
data: [],
}
}
componentDidMount() {
fetch('http://localhost:3000/api/users')
.then(response => response.json())
.then(data => this.setState({ data }))
}
render() {
return(
<div className="table">
<h1>LOL</h1>
<p>{this.state.data[1].email}</p>
</div>
)
}
}
Upvotes: 1
Views: 683
Reputation: 3403
The problem is that, when your component starts the rendering, the this.state.data[1].email
wasn't loaded already. Just check if the data was already loaded, like below:
render(){
if(this.state.data.length > 0)
return(
<div className="table">
<h1>LOL</h1>
<p>{this.state.data[1].email}</p>
</div>
)
else return <div/>
}
The other possible solution is to use the map
function. It will only render something when the array it's filled. The code is below:
render(){
return(
<div className="table">
<h1>LOL</h1>
{ this.state.data.map(user => <p>{user.email}</p>) }
</div>
)
}
For each user in the data
array, the component will render a tag <p>
with the email. When there's nothing in the array, the component will render nothing.
Upvotes: 1
Reputation: 34014
This.state.data initially set to an empty array. So when your component first time renders it will be an empty array.
In componentDidMount you are making an api call and assigning api response to the state data. So this method gets called after first render
The reason you get that issue because you are accessing 1st index from this.state.data array which is obviously an empty array at the time of first render. So what you have to do is
Change
<p>{this.state.data[1].email}</p>
To
<p>{this.state.data.length > 0 && this.state.data[1].email}</p>
Or do iterate the array and render p elements
{this.state.data.length > 0 && this.state.data.map(d => (
<p key={d.id}>d.email}</p>
)}
If you don’t have unique id per object in array then use index as key
Upvotes: 0
Reputation: 5717
its a common error the request didn't complete before the render method is called just add an if statement
render () {
const { data } = this.state
return (
<div className='table'>
<h1>LOL</h1>
{data.length > 0 && <p>{data[1].email}</p>}
</div>
)
}
Upvotes: 0