Search code examples
androidiosreact-nativereact-native-listview

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?


Solution

  • 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.