What's React Native's new FlatList?


(Skcript Bot) #1

Earlier in React Native, for showing a list of items we’ve used the ListView component and sometimes for simplicity we’ve used ScrollView as well.

But the problem arises when you’re handling a huge data set, say 1000s of items inside the page. These components are not that efficient to handle such a big list.

Thankfully the team has brought a new component FlatList for handling bigger lists. The main idea behind this is that only the visible items are rendered and stored in the memory while others stay out of the memory, thus even if there are 1000s in terms of data, only 10 or 15 will be rendered at once.

Getting Started

Import the component from react-native package just like any other React Native component.

import { FlatList } from 'react-native';

Important Props

Before heading to the actual implementation I’ll explain the basic key props that are necessary for using the component.

  • data - The array of items that need to be listed.
  • renderItem - Function that returns the component of each item.
  • keyExtractor - Extract the key of each item: it can be the index or any unique field in the data.

Simple Implementation

Let’s build a conversation screen with FlatList, here assume that the guy is very popular and has a lot of conversations (say 1000)

Sample Data

The data that is passed as prop should be an array of objects. For example just like below.

var data = [
  {"id":1,"name":"Charil","last_message":"exploit proactive functionalities","picture":"url","time":"29/10/2016"},
  {"id":1,"name":"Charil","last_message":"exploit proactive functionalities","picture":"url","time":"29/10/2016"},
  {"id":1,"name":"Charil","last_message":"exploit proactive functionalities","picture":"url","time":"29/10/2016"},
];

The Component

Once you have the data you can now render the component like below and passing the corresponding props.

<FlatList 
  keyExtractor={this._keyExtractor}
  data={this.state.data}
  renderItem={this.renderItem.bind(this)}
/>

As you see in the above code it is a mix of both ScrollView and ListView, here we’re not creating any data source and it’s very straightforward, thus reducing the complexity of the rendering each element.

Item Render Function

The function that has been passed as renderItem prop will be used to return the component that will be rendered for each item.

renderItem(data) {
    let { item, index } = data;
    return (
      <View style={styles.itemBlock}>
        <Image source={{uri: item.picture}} style={styles.itemImage}/>
        <View style={styles.itemMeta}>
          <Text style={styles.itemName}>{item.name}</Text>
          <Text style={styles.itemLastMessage}>{item.last_message}</Text>
        </View>
      </View>
    ) 
  }

This function takes an object parameter that has the current instance item and the index as the fields. Thus we are extracting the item and the index and using it inside the return. Also if you notice we’re not creating key prop here as it’s handled by keyExtractor function.

The Styling

To make it look better we’ve added few styles.

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 20,
  },
  itemBlock: {
    flexDirection: 'row',
    paddingBottom: 5,
  },
  itemImage: {
    width: 50,
    height: 50,
    borderRadius: 25,
  },
  itemMeta: {
    marginLeft: 10,
    justifyContent: 'center',
  },
  itemName: {
    fontSize: 20,
  },
  itemLastMessage: {
    fontSize: 14,
    color: "#111",
  }
});

Now if you see the list, it looks like this.

Scrolling through 1000 items

Additional Settings

FlatList comes with more features like Header support, Footer support, Separator support, Pull to Refresh etc.

Let’s try adding these to our list.

Header & Footer

For creating a header and footer for the list you can use the custom components and pass it to the ListHeaderComponent and ListFooterComponent props.

renderHeader() {
  return (
    <View style={styles.header}>
      <Text style={styles.headerText}>Conversations</Text>
    </View>
  )
}
<FlatList 
  ...
  ListHeaderComponent={this.renderHeader}
  ...
/>

Separator

Separators are usually built with border property, but if you want something more than just a line you can use ItemSeparatorComponent to render custom separator.

I’ve created a simple line with a smaller width just to differentiate from border like below.

// Function to render the separator component.
renderSeparator() {
  return <View style={styles.separator} />
}
// Style for the separator
const styles = StyleSheet.create({
  ...
  separator: {
    height: 0.5,
    width: "80%",
    alignSelf: 'center',
    backgroundColor: "#555"
  }
  ...
});

Refresh Control

When you have a very highly dynamic list which will change over time, we should provide the user an ability to refresh the content whenever they wish. That’s why we have RefreshControl component and it went well with FlatList as well. You can use it like the one below.

Import the RefreshControl Component first.

import {
  ...
  RefreshControl
  ...
} from 'react-native';

And now I’ve created a function that will mock the refresh functionality with a timeout.

_onRefresh() {
  this.setState({
    refreshing: true
  })
  setTimeout(function() {
    this.setState({
      refreshing: false
    })
  }.bind(this),1000)
}

And finally, pass the RefreshControl component to FlatList as props.

refreshControl={
  <RefreshControl
    refreshing={this.state.refreshing}
    onRefresh={this._onRefresh.bind(this)}
  />
}

Pull To Refresh

Other Supports

FlatList will support most of the ScrollView props as well, the few important things are.

  • bounces
  • onScrollEndDrag
  • onMomentumScrollEnd
  • onScroll
  • scrollEventThrottle
  • showsVerticalScrollIndicator

So, if you’re looking for a list component that works even with large data set, FlatList is your right choice.

The complete source code of this sample application is here


This is a companion discussion topic for the original entry at https://www.skcript.com/svr/whats-react-natives-new-flatlist/