Can't access properties in JavaScript object array (React.js)
I have a React.js component that retrieves its initial state data from an API call in componentDidMount (). The data is an array of objects.
I can view the array and individual elements using JSON.stringify (for debugging), but when I try to access a property on the element, I get an error that seems to imply that the element is undefined despite checking 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>
);
}
}
Mistake:
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 notoriously limited knowledge of React.js, I suspect this is because React.js is trying to access the .id property before componentDidMount () triggers loading the initial state data, thus returning an undefined value, but I could be completely wrong.
Can anyone point me in the right direction?
source to share
How do you retrieve data from an API call when the initial render data is not available, so you get an 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>
);
}
source to share
this is because you have an async request and since the states array is initially empty it is this.state.tubedata[0]
initially undefined
Save validation 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>
source to share