I’m having trouble accessing an array of objects in my JSON data to display in a React Native Text ponent.
JSON data
{
"name": "Pizza Joint",
"when": [{
"day": ["Sat", "Sun"],
"start_time": "11:00",
"end_time": "23:00"
}]
}
Code
<View style={styles.container}>
<Text style={styles.name}>{venue.name}</Text>
<Text style={styles.time}>{venue.when[0].start_time}</Text>
</View>
This throws the error Undefined is not an object (evaluating 'venue.when')
which I don't understand since console.log(type of venue.when)
returns object
.
How can I access the when
object properties here?
Additional notes
I copied the app structure from this tutorial.
Here is VenueList.js
:
'use strict';
var React = require('react-native');
var VenueDetail = require('./VenueDetail');
var {
Image,
StyleSheet,
Text,
View,
Component,
ListView,
TouchableHighlight,
ActivityIndicatorIOS
} = React;
var styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
padding: 10
},
thumbnail: {
width: 53,
height: 81,
marginRight: 10
},
rightContainer: {
flex: 1,
},
title: {
fontSize: 20,
marginBottom: 8
},
author: {
color: '#656565'
},
separator: {
height: 1,
backgroundColor: '#dddddd'
},
listView: {
backgroundColor: '#F5FCFF'
},
loading: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
});
// var REQUEST_URL = ':fiction';
var REQUEST_URL = '';
class VenueList extends Component {
render() {
if (this.state.isLoading) {
return this.renderLoadingView();
}
console.log(this.state.dataSource);
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderVenue.bind(this)}
style={styles.listView}
/>
);
}
renderLoadingView() {
return (
<View style={styles.loading}>
<ActivityIndicatorIOS
size='large'/>
<Text>
Loading venues...
</Text>
</View>
);
}
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2
})
};
}
ponentDidMount() {
this.fetchData();
}
fetchData() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData),
isLoading: false
});
})
.done();
}
renderVenue(venue) {
console.log(venue);
return (
<TouchableHighlight onPress={() => this.showVenueDetail(venue)} underlayColor='#dddddd'>
<View>
<View style={styles.container}>
<Image
// source={{uri: venue.images[0].url}}
style={styles.thumbnail} />
<View style={styles.rightContainer}>
<Text style={styles.title}>{venue.name}</Text>
<Text style={styles.author}>{venue.subtitle}</Text>
</View>
</View>
<View style={styles.separator} />
</View>
</TouchableHighlight>
);
}
}
module.exports = VenueList;
console.log(venue)
produces the following format of data (I am simplifying output here for the purposes of the example):
{
name: 'Pizza Joint',
when: [{
day: ['Sat', 'Sun'],
start_time: '11:00',
end_time: '23:00'
}]
}
I notice the above is not JSON since the quotes on the keys have been stripped out.
I’m having trouble accessing an array of objects in my JSON data to display in a React Native Text ponent.
JSON data
{
"name": "Pizza Joint",
"when": [{
"day": ["Sat", "Sun"],
"start_time": "11:00",
"end_time": "23:00"
}]
}
Code
<View style={styles.container}>
<Text style={styles.name}>{venue.name}</Text>
<Text style={styles.time}>{venue.when[0].start_time}</Text>
</View>
This throws the error Undefined is not an object (evaluating 'venue.when')
which I don't understand since console.log(type of venue.when)
returns object
.
How can I access the when
object properties here?
Additional notes
I copied the app structure from this tutorial.
Here is VenueList.js
:
'use strict';
var React = require('react-native');
var VenueDetail = require('./VenueDetail');
var {
Image,
StyleSheet,
Text,
View,
Component,
ListView,
TouchableHighlight,
ActivityIndicatorIOS
} = React;
var styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
padding: 10
},
thumbnail: {
width: 53,
height: 81,
marginRight: 10
},
rightContainer: {
flex: 1,
},
title: {
fontSize: 20,
marginBottom: 8
},
author: {
color: '#656565'
},
separator: {
height: 1,
backgroundColor: '#dddddd'
},
listView: {
backgroundColor: '#F5FCFF'
},
loading: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
});
// var REQUEST_URL = 'https://www.googleapis./books/v1/volumes?q=subject:fiction';
var REQUEST_URL = 'http://apib.miniguide.es/wall/today';
class VenueList extends Component {
render() {
if (this.state.isLoading) {
return this.renderLoadingView();
}
console.log(this.state.dataSource);
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderVenue.bind(this)}
style={styles.listView}
/>
);
}
renderLoadingView() {
return (
<View style={styles.loading}>
<ActivityIndicatorIOS
size='large'/>
<Text>
Loading venues...
</Text>
</View>
);
}
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2
})
};
}
ponentDidMount() {
this.fetchData();
}
fetchData() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData),
isLoading: false
});
})
.done();
}
renderVenue(venue) {
console.log(venue);
return (
<TouchableHighlight onPress={() => this.showVenueDetail(venue)} underlayColor='#dddddd'>
<View>
<View style={styles.container}>
<Image
// source={{uri: venue.images[0].url}}
style={styles.thumbnail} />
<View style={styles.rightContainer}>
<Text style={styles.title}>{venue.name}</Text>
<Text style={styles.author}>{venue.subtitle}</Text>
</View>
</View>
<View style={styles.separator} />
</View>
</TouchableHighlight>
);
}
}
module.exports = VenueList;
console.log(venue)
produces the following format of data (I am simplifying output here for the purposes of the example):
{
name: 'Pizza Joint',
when: [{
day: ['Sat', 'Sun'],
start_time: '11:00',
end_time: '23:00'
}]
}
I notice the above is not JSON since the quotes on the keys have been stripped out.
Share Improve this question edited Apr 28, 2016 at 11:17 Michael Mueller asked Apr 27, 2016 at 21:13 Michael MuellerMichael Mueller 3112 gold badges4 silver badges15 bronze badges 5-
is
{venue.when[0].start_time]}
a typo and did you write{venue.when[0].start_time}
? – VonD Commented Apr 27, 2016 at 21:19 - yes, a typo, fixing sorry – Michael Mueller Commented Apr 27, 2016 at 21:22
-
The path access in the render code seems to be correct, there must be some problem with the way your passing the
venue
in render function. Try to console.log the venue object before rendering it. – Risto Novik Commented Apr 27, 2016 at 21:26 -
How is
venue
exposed to your ponent ? Are you looping through a list fo venues ? Could you show whatconsole.log(venue)
outputs before rendering the View ? – VonD Commented Apr 27, 2016 at 21:26 - do you set the initial state for the venue also, because if not it would be for start empty until you make a fetch request. – Risto Novik Commented Apr 28, 2016 at 6:56
1 Answer
Reset to default 4Ok I figured it out. The problem was the JSON data set that our API produces has some documents with another definition that delimit the data (e.g. first is document that indicates featured
). So React was throwing an error on the first document, which lacked the properties I was attempting to access.
To fix this, I added ternary expressions to the React ponents to check for the existence of properties:
renderVenue(venue) {
console.log(venue);
return (
<TouchableHighlight onPress={() => this.showVenueDetail(venue)} underlayColor='#dddddd'>
<View>
<View style={styles.container}>
<Image source={ 'images' in venue ? { uri: 'http://' + venue.images[0].url } : null}
style={styles.thumbnail} />
<View style={styles.rightContainer}>
<Text style={styles.title}>{venue.name}</Text>
<Text style={styles.author}>{venue.subtitle}</Text>
<Text style={styles.author}>{ 'when' in venue ? venue.when[0].start_date : null}</Text>
</View>
</View>
<View style={styles.separator} />
</View>
</TouchableHighlight>
);
}
}
Perhaps we should modify our API output.
In any event thanks for ments, they were helpful.