3

I have a React.js component which pulls its initial state data from an API call in componentDidMount(). The data is an array of objects.

I am able to view the array, and individual elements using JSON.stringify (for debugging), but when I try to access a property in an element, I get an error which seems to imply that the element is undefined, despite having checked that it is not.

Code:

class TubeStatus extends Component {
  constructor(props) {
    super(props);
    this.state = { 'tubedata' : [] };
  };
  componentWillMount() {
    let component = this;
    axios.get('https://api.tfl.gov.uk/line/mode/tube/status')
    .then( function(response) {
      component.setState({ 'tubedata' : response.data });
    })
    .catch( function(error) {
      console.log(JSON.stringify(error, null, 2));
    });
  };
  render() {
    return (
      <div><pre>{this.state.tubedata[0].id}</pre></div>
    );
  }
}

Error:

Uncaught TypeError: Cannot read property 'id' of undefined

If I use JSON.stringify() to display this.state.tubedata, all the data is there.

In my admittedly limited knowledge of React.js, I suspect this is because React.js is trying to access the .id property before componentDidMount() fires loading the initial state data, thus returning undefined, but I could be completely wrong.

Anyone able to point me in the right direction?

2 Answers 2

3

As you are fetching data from API call, on initial rendering data is not available hence you are getting error.

this.state.tubedata.length>0// check if tubedata is available 

So,

 render() {
    return (
      <div><pre>{this.state.tubedata.length>0?this.state.tubedata[0].id:null}</pre></div>
    );
  }
Sign up to request clarification or add additional context in comments.

1 Comment

Figured as much. Thanks a lot!
1

this is because you are having a async request and since the state array is initially empty this.state.tubedata[0] is initially undefined

Keep a check before using id like

<div><pre>{this.state.tubedata.length > 0 && this.state.tubedata[0].id}</pre></div>

class TubeStatus extends React.Component {
  constructor(props) {
    super(props);
    this.state = { 'tubedata' : [] };
  };
  componentWillMount() {
    let component = this;
    
  };
  render() {
    return (
      <div>Hello <pre>{this.state.tubedata.length > 0 && this.state.tubedata[0].id}</pre></div>
    );
  }
} 
ReactDOM.render(<TubeStatus/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

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.