1

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>
    )
  }
}
3
  • 1
    please add all the component code . you probably didn't initialised the state and render the component Commented Nov 17, 2018 at 1:06
  • @NaorTedgi sure, updated the post. Commented Nov 17, 2018 at 1:11
  • yap it is what I suspect. check the answer below Commented Nov 17, 2018 at 1:26

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Is there a way to only render the component if data is fully loaded without flooding the code with an extra if statement? I have never seen such construction in production-ready code.
The if is already only rendering the component if the data is fully loaded. But, I'll add a possible solution to my answer.
0

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>
    )
  }

4 Comments

Is there a way to avoid such an if statement? It seems to be complicating the code for no reason.
you always have to return value from the render method. there is all kind of ways to avoid it both its depends on your app component hierarchy
i think this is the same issue here stackoverflow.com/questions/45808247/… see Appunni M answer
@PeterChudinov i Update to something more elegant
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.