FlatList & SectionList
Master FlatList and SectionList components for efficient rendering of large lists in React Native applications. This is a foundational concept in cross-platform mobile development that professional developers rely on daily. The explanations below are written to be beginner-friendly while covering the depth and nuance that comes from real-world React Native experience. Take your time with each section and practice the examples
FlatList Component
FlatList is a performant interface for rendering basic, flat lists with support for most common use cases like horizontal mode, header/footer, pull-to-refresh, and more.. This is an essential concept that every React Native developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
FlatList Properties
- data - Array of items to render — a critical concept in cross-platform mobile development that you will use frequently in real projects
- renderItem - Function to render each item — a critical concept in cross-platform mobile development that you will use frequently in real projects
- keyExtractor - Function to extract unique keys — a critical concept in cross-platform mobile development that you will use frequently in real projects
- getItemLayout - Optimize performance with known item dimensions
- onEndReached - Callback when reaching the end — a critical concept in cross-platform mobile development that you will use frequently in real projects
- refreshing - Pull-to-refresh state — a critical concept in cross-platform mobile development that you will use frequently in real projects
- onRefresh - Pull-to-refresh callback — a critical concept in cross-platform mobile development that you will use frequently in real projects
SectionList Component
SectionList is a performant interface for rendering sectioned lists with support for sticky section headers, section separators, and more.. This is an essential concept that every React Native developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Performance Optimization
Use getItemLayout, keyExtractor, and removeClippedSubviews for optimal performance with large datasets.. This is an essential concept that every React Native developer must understand thoroughly. In professional development environments, getting this right can mean the difference between code that works reliably and code that breaks in production. The following sections break this down into clear, digestible pieces with practical examples you can try immediately
Advanced FlatList Example
import React, { useState, useEffect } from 'react';
import { View, Text, FlatList, TouchableOpacity, StyleSheet, RefreshControl, ActivityIndicator } from 'react-native';
const AdvancedFlatList = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
const [refreshing, setRefreshing] = useState(false);
const [page, setPage] = useState(1);
const loadData = async (pageNum = 1, isRefresh = false) => {
if (isRefresh) {
setRefreshing(true);
} else {
setLoading(true);
}
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1000));
const newData = Array.from({ length: 20 }, (_, i) => ({
id: (pageNum - 1) * 20 + i + 1,
title: `Item ${(pageNum - 1) * 20 + i + 1}`,
subtitle: `This is subtitle for item ${(pageNum - 1) * 20 + i + 1}`,
timestamp: new Date().toISOString(),
}));
if (isRefresh) {
setData(newData);
setPage(1);
} else {
setData(prev => [...prev, ...newData]);
setPage(pageNum);
}
} catch (error) {
console.error('Error loading data:', error);
} finally {
setLoading(false);
setRefreshing(false);
}
};
useEffect(() => {
loadData();
}, []);
const onRefresh = () => {
loadData(1, true);
};
const onEndReached = () => {
if (!loading) {
loadData(page + 1);
}
};
const renderItem = ({ item, index }) => (
<TouchableOpacity style={styles.item}>
<Text style={styles.itemTitle}>{item.title}</Text>
<Text style={styles.itemSubtitle}>{item.subtitle}</Text>
<Text style={styles.itemTimestamp}>
{new Date(item.timestamp).toLocaleString()}
</Text>
</TouchableOpacity>
);
const renderHeader = () => (
<View style={styles.header}>
<Text style={styles.headerTitle}>Advanced FlatList</Text>
<Text style={styles.headerSubtitle}>Pull to refresh, infinite scroll</Text>
</View>
);
const renderFooter = () => {
if (!loading) return null;
return (
<View style={styles.footer}>
<ActivityIndicator size="small" color="#2196F3" />
<Text style={styles.footerText}>Loading more...</Text>
</View>
);
};
const renderEmpty = () => (
<View style={styles.empty}>
<Text style={styles.emptyText}>No data available</Text>
</View>
);
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item.id.toString()}
ListHeaderComponent={renderHeader}
ListFooterComponent={renderFooter}
ListEmptyComponent={renderEmpty}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={onRefresh}
colors={['#2196F3']}
tintColor="#2196F3"
/>
}
onEndReached={onEndReached}
onEndReachedThreshold={0.5}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={10}
initialNumToRender={10}
getItemLayout={(data, index) => ({
length: 80,
offset: 80 * index,
index,
})}
style={styles.container}
/>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
header: {
backgroundColor: '#2196F3',
padding: 20,
alignItems: 'center',
},
headerTitle: {
fontSize: 24,
fontWeight: 'bold',
color: 'white',
marginBottom: 5,
},
headerSubtitle: {
fontSize: 16,
color: 'rgba(255, 255, 255, 0.8)',
},
item: {
backgroundColor: 'white',
padding: 15,
marginHorizontal: 10,
marginVertical: 5,
borderRadius: 8,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
itemTitle: {
fontSize: 18,
fontWeight: 'bold',
color: '#333',
marginBottom: 5,
},
itemSubtitle: {
fontSize: 14,
color: '#666',
marginBottom: 5,
},
itemTimestamp: {
fontSize: 12,
color: '#999',
},
footer: {
padding: 20,
alignItems: 'center',
},
footerText: {
marginTop: 10,
fontSize: 14,
color: '#666',
},
empty: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 40,
},
emptyText: {
fontSize: 16,
color: '#999',
},
});
export default AdvancedFlatList;