Are you dealing with a scenario where you want to show a lot of data in a list? You should probably check React Natives new FlatList Component.
ScrollViews & ListViews
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
Up next
Accelerated Mobile Pages (AMP) using Middleman