Перейти к содержимому

8. FlatList и списки

FlatList — виртуализированный список для больших наборов данных. Рендерит только видимые элементы, остальные уничтожает. Обязателен при >50 элементах.

import { FlatList, Text, View, StyleSheet } from 'react-native';
const data = [
{ id: '1', title: 'Элемент 1' },
{ id: '2', title: 'Элемент 2' },
// ...
];
<FlatList
data={data}
keyExtractor={(item) => item.id}
renderItem={({ item, index }) => (
<View style={styles.item}>
<Text>{item.title}</Text>
</View>
)}
/>
<FlatList
horizontal={true}
showsHorizontalScrollIndicator={false}
data={stories}
keyExtractor={(item) => item.id}
renderItem={({ item }) => <StoryCard story={item} />}
contentContainerStyle={{ paddingHorizontal: 16, gap: 12 }}
/>
import { FlatList, RefreshControl } from 'react-native';
const [refreshing, setRefreshing] = useState(false);
const onRefresh = async () => {
setRefreshing(true);
await fetchData();
setRefreshing(false);
};
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={onRefresh}
tintColor="#cba6f7"
/>
}
/>
import { SectionList, Text, View } from 'react-native';
const sections = [
{ title: 'Сегодня', data: ['Задача 1', 'Задача 2'] },
{ title: 'Вчера', data: ['Задача 3'] },
];
<SectionList
sections={sections}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => (
<View style={styles.item}>
<Text>{item}</Text>
</View>
)}
renderSectionHeader={({ section: { title } }) => (
<Text style={styles.sectionHeader}>{title}</Text>
)}
/>
const [data, setData] = useState([]);
const [page, setPage] = useState(1);
const [loading, setLoading] = useState(false);
const [hasMore, setHasMore] = useState(true);
const loadMore = async () => {
if (loading || !hasMore) return;
setLoading(true);
const newData = await fetchPage(page);
if (newData.length === 0) setHasMore(false);
setData(prev => [...prev, ...newData]);
setPage(p => p + 1);
setLoading(false);
};
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
onEndReached={loadMore}
onEndReachedThreshold={0.5} // Загружать когда 50% до конца
ListFooterComponent={loading ? <ActivityIndicator /> : null}
/>
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id}
// Оптимизации производительности:
removeClippedSubviews={true} // Unmount невидимые элементы (Android)
maxToRenderPerBatch={10} // Элементов за один рендер батч
updateCellsBatchingPeriod={50} // ms между батчами
windowSize={10} // Размер окна рендера (в экранах)
initialNumToRender={10} // Первоначальный рендер
getItemLayout={(data, index) => ({ // Если высота фиксирована
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
/>

FlashList от Shopify — замена FlatList с 10x лучшей производительностью:

Окно терминала
npx expo install @shopify/flash-list
import { FlashList } from "@shopify/flash-list";
<FlashList
data={data}
renderItem={({ item }) => <Item item={item} />}
estimatedItemSize={80} // Примерная высота элемента
/>