Reputation: 2751
I'm building a small app that consumes a REST api. I'm running into problems displaying information inside arrays of objects, see code below:
actions.js
import axios from 'axios'
function fetchService () {
return axios.get('http://localhost:5000/ldbws-rest-proxy/v0.1/departure-board/IPS')
.then(function (response) {
return {
service: response.data.trainServices[0]
}
})
.catch(function (response) {
console.log(response)
})
}
export default fetchService
train_service.js
import fetchService from '../actions'
import DepartureTime from './departure_time'
import OriginStation from './origin_station'
var TrainService = React.createClass ({
getInitialState () {
return {
service: []
}
},
componentDidMount () {
fetchService()
.then(function (dataObj) {
this.setState({
service: dataObj.service
})
}.bind(this))
},
render () {
return (
<section>
<DepartureTime time={this.state.service.std} />
<OriginStation name={this.state.service.origin[0].crs} />
</section>
)
}
})
export default TrainService
JSON sample (response.data.trainServices[0])
{
"destination": [
{
"crs": "CBG",
"locationName": "Cambridge"
}
],
"etd": "On time",
"operator": "Greater Anglia",
"operatorCode": "LE",
"origin": [
{
"crs": "IPS",
"locationName": "Ipswich"
}
],
"serviceID": "ILZn7gyLj+eoZZfyaFlP0w==",
"std": "12:20"
}
The problem is that <OriginStation name={this.state.service.origin[0].crs} />
throws an error:
TypeError: undefined is not an object (evaluating 'this.state.service.origin')
I'm not sure why this isn't working, if I do console.log(dataObj.service.origin[0].crs)
inside componentDidMount it outputs fine. I think it's something to do with the origin array...
Any help appreciated.
EDIT:
Screenshot of the state in the Chrome Inspector:
Upvotes: 2
Views: 677
Reputation: 989
It's because your TrainService
render method calls earlier than fetchService
promise resolves.
Easiest way to fix your error is wait for fetchService
updates service
state:
var TrainService = React.createClass ({
getInitialState () {
return {
service: null
}
},
componentDidMount () {
fetchService()
.then(function (dataObj) {
this.setState({
service: dataObj.service
})
}.bind(this))
},
render () {
if (this.state.service === null)
return null;
return (
<section>
<DepartureTime time={this.state.service.std} />
<OriginStation name={this.state.service.origin[0].crs} />
</section>
)
}
})
Upvotes: 2
Reputation: 1377
fetchService
is making an async call. So when componentDidMount
is run, it will make an async call and proceeds to render
.
When the render
function is executed for the first time you state is not populated with the data and it has an empty array for this.state.service
, from getInitialState
.
If you are writing console.log inside componentDidMount as
componentDidMount () {
fetchService()
.then(function (dataObj) {
console.log(dataObj.service.origin[0].crs)
this.setState({
service: dataObj.service
})
}.bind(this))
},
the console.log gets executed only when the async call has succeeded, so the data is available.
To solve this either don't render the component until the state data is ready.
render() {
this.state.service.length == 0 && return null
...
}
Upvotes: 0