Adrian Sicaru Adrian Sicaru - 4 months ago 35
iOS Question

Populate ListView from web service in React Native

I have this piece of react-native code:

import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
ToolbarAndroid,
ListView,
Text,
View
} from 'react-native';

let styles = require('./styles/styles');

class Sunshine extends Component {

constructor(props) {
super(props);
this.state = {isLoading: true, jsonData: ''}

}
componentDidMount() {
this.setState({jsonData: this.getMoviesFromApiAsync()})
}
render() {
if(this.state.isLoading != true) {
return (
<View style={styles.container}>
<ToolbarAndroid
style={styles.baseToolbar}
logo={require('./ic_launcher.png')}
title="Sunshine"
titleTextColor="red"/>
<View style={styles.viewcontainer}>
<Text>{this.state.jsonData.city.id}</Text>
<ListView
dataSource={this.state.jsonData.list}
renderRow={(rowData) => <Text>{rowData.dt}</Text>}
/>
</View>
</View>
);
} else {
return (
<View style={styles.container}>
<ToolbarAndroid
style={styles.baseToolbar}
logo={require('./ic_launcher.png')}
title="Sunshine"
titleTextColor="red"/>
<View style={styles.singleviewcontainer}>
<Text>Loading...</Text>
</View>
</View>
);
}

}

getMoviesFromApiAsync() {
return fetch('http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=14&APPID=18dcba27e5bca83fe4ec6b8fbeed7827')
.then((response) => response.json())
.then((responseJson) => {
this.setState({isLoading: false, jsonData: responseJson});
console.log(responseJson);
return responseJson;
})
.catch((error) => {
console.error(error);
});
}

}

AppRegistry.registerComponent('Sunshine', () => Sunshine);


What I think it should happen is that when an answer arrives from the server, the list is populated with it's result. But that's not what's going on. Intsead i get this error:

undefined is not an object (evaluating 'allRowIDs.length')


So what exactly am i doing wrong here?

amb amb
Answer

You have to create a ListViewDataSource with the data list.

constructor (props) {
  super(props)
  this.dataSource = new ListView.DataSource({
    rowHasChanged: (r1, r2) => r1 !== r2
  })
}

componentDidMount () {
  // You don't need to assign the return value to the state
  this.getMoviesFromApiAsync()
}

render () {
  // Use the dataSource
  const rows = this.dataSource.cloneWithRows(this.state.jsonData.list || [])
  ...
  return (
    ...
    <ListView
      dataSource={rows}
    />
  )
}

Full docs here.