Zach Thornton
Zach Thornton

Reputation: 13

When to make a Fetch call for React Native Component

I'm new to React Native and confused on how to properly utilize the provided Fetch API.

The call itself (as outlined here: http://facebook.github.io/react-native/docs/network.html) is straightforward, and I can log out a successful response, but when it comes time to render the data, it's undefined.

I would expect that I could define an empty 'movies' array, and then replace it by calling 'setState' from componentDidMount(), which would trigger a re-render. Is this assumption incorrect?

The code sample below results in the following error:

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

Thanks in advance for any help!

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

class ReactNativePlayground extends Component {

   constructor() {
      super();
      this.state = {
         movies: []
      }
   }

   componentDidMount() {
      fetch('https://facebook.github.io/react-native/movies.json')
      .then((response) => response.json())
      .then((responseJson) => {
         this.setState({
            movies: responseJson.movies
         })
      })
      .catch((error) => {
         console.error(error);
      });
   }

   render() {
      return (
         <View>
            <Text>test</Text>
            <ListView
               dataSource={this.state.movies}
               renderRow={(row) => <Text>{row.title}</Text>}
            />
         </View>
      )
   }
}

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

Upvotes: 1

Views: 585

Answers (1)

Tom Walters
Tom Walters

Reputation: 15616

That's because you need to place the data into a ListView.DataSource:

constructor (props) {
  super(props);

  const ds = new ListView.DataSource({
    rowHasChanged: (a, b) => a !== b
  })

  this.state = {
    movies: ds.cloneWithRows([])
  }
}

// Inside the response JSON:

this.setState({
  movies: this.state.movies.cloneWithRows(responseJson.movies)
});

The React Native ListView docs demonstrate this kind of setup. Using the datasource allows for optimisations to be made when rendering lists of data (notice the rowHasChanged function for instance - which prevents needless re-rendering of a row when the data hasn't altered.

Upvotes: 2

Related Questions