React Native FlatList with Web Service Data

For those who is familiar with ListView (which is now deprecated), FlatList has a similar approach but it is better performance with more features. This what ListView looks like below where it allows us to bind to a data source that contain a list of data.

Notice that ListView has dataSource and renderRow attributes. The dataSource point to a list of objects in this case string. The renderRow point to inline arrow function that return the Text. So for each item in the list, it will call this method to create Text component.

Similarly in FlatList, it has the following:

<FlatList
data={dataObj}
renderItem={({item}) => <Text>{item.title}</Text> }
/>

dataObj is just a list of objects like below:

const dataObj = [
{title: 'Text', key: '1'},
{title: 'Text 2', key: '2'},
{title: 'Text 3', key: '3'},
];

Full code so far:


Bind to Web Service Data

The FlatList can bind to external data instead of hard coded string. One playground URL that we can use is this publicly host API from randomuser.me. The url we are using is:

https://randomuser.me/api/?seed=1&page=1&results=10

Just point your browser to the above url, and you get the follow response:

{"results":[{
"gender":"male",
"name":{"title":"mr","first":"janique","last":"costa"},
...
"email":"janique.costa@example.com",
...
"phone":"(84) 5181-4592",
"cell":"(23) 6323-6609",
...
"picture":{
"large":"https://randomuser.me/api/portraits/men/42.jpg",
"medium":"https://randomuser.me/api/portraits/med/men/42.jpg",
"thumbnail":"https://randomuser.me/api/portraits/thumb/men/42.jpg"},
"nat":"BR"
},...
]

We use fetch method to get data from remote url in our code. Then save the data to state data object. We will use data object to display in the list.

So in the constructor will create a method to fetch the data by calling getRemoteData method. In the constructor we need to make sure we have state initialized so setState can set data object.

constructor() {
...
  this.state = { };
this.getRemoteData();
}

Below is the getRemoteData method:

getRemoteData = () => {
const url = "https://randomuser.me/api/?results=10";
fetch(url)
.then(res => res.json())
.then(res => {
this.setState({
data: res.results
});
})
.catch(error => {
console.log("get data error:" + error);
});
}

Then in the FlatList renderItem, we point to a method renderNativeItem (will show below) and pass in item. These are list of items from this.state.data.

<FlatList
data={this.state.data}
renderItem={({item}) => this.renderNativeItem(item)}
/>

Then we update the GUI to have a little more fancy look. We are going to use react-native-elements to show each item as ListElement.

First let’s install react-native-elements by running:

npm install --save react-native-elements

In the import, we need to expose ListItem like this:

import { ListItem } from "react-native-elements"

Then in the renderItem property, we point to renderNativeItem method, use ListItem, with title, subtitle, and avatar attributes. The avatar will point to the uri in the item.picture.thumbnail.

So it looks something like this in the renderNativeItem method:

renderNativeItem = (item) => {
return <ListItem
title={item.name.first}
subtitle={item.email}
avatar={{ uri: item.picture.thumbnail }}
/>;
}

Now we should able to get the list display like this:

Lets add the onPress for the item to show detail page with item data pass through navigation.

<ListItem
...
onPress={() => this.onPressItem(item)}
/>

Now create the onPressItem method:

onPressItem = (item) => {
const email = item.email;
console.log("onPress email with item: " + item.email);
this.props.navigation.navigate('Detail', {item: item})
}

Now in the DetailScreen, let’s pickup the item and display it with bigger image. So in the render method, use the props.navigation.state.params to pick up item object like this:

const item = this.props.navigation.state.params.item;
...
<Text style={styles.text}>email: {item.email}</Text>

Now you can display in the Text component by reference it as item.email for example. So now you can press on the item and show the detail in DetailScreen.

Here is the final code:

More to add (see links below on related tutorial):

  1. activity indicator
  2. search bar
  3. infinite scroll

Internally hosted JSON API

To create your own web service to output your custom data, you can create internal JSON API with json-server.

npm install json-server

First create a json file call users.json with the following data. The data must be an object as its root with array items.

{"users": [
{
"name": "Proxima Midnight",
"email": "proxima@a.com"
},
{
"name": "Ebony Maw",
"email": "ebony@a.com"
}
]}

Now, start the json-server where you saved the json file:

json-server --watch users.json

To fetch data:

const URI = 'http://localhost:5200';  
try {
let response = await fetch(URI + '/users');
let responseJsonData = await response.json();
// do something with responseJsonData
this.setState({data: responseJsonData});
} catch(e) {
console.log(e)
}

Notice that you can’t test this on Expo with localhost. You must run simulator locally. For Expo, you will need to update the URI to match Expo url.

See next: Simple Gifted Chat using Firebase and ability to upload avatar

References:

https://medium.com/react-native-development/how-to-use-the-flatlist-component-react-native-basics-92c482816fe6

https://medium.freecodecamp.org/how-to-build-a-react-native-flatlist-with-realtime-searching-ability-81ad100f6699