SectionList — komponent React Native do wyświetlania list sekcjonowanych z grupowaniem elementów według kategorii. W przeciwieństwie do FlatList, SectionList przyjmuje tablicę sekcji z nagłówkami i danymi, co pozwala tworzyć indeksy alfabetyczne, katalogi i menu. Komponent obsługuje sticky headers — przypięte nagłówki podczas przewijania. Więcej o API list przeczytasz w oficjalnym przewodniku Meta.
Najważniejsze
SectionList — komponent React Native do wyświetlania danych pogrupowanych w logiczne sekcje. Każda sekcja ma nagłówek i listę elementów, co jest idealne dla kontaktów alfabetycznie, menu według kategorii, zamówień według dat. Komponent jest zbudowany na VirtualizedList i dziedziczy wszystkie zalety wirtualizacji.
SectionList pojawił się razem z FlatList w React Native 0.43 i od tego czasu jest standardem dla kategoryzowanych list. Według danych Meta (2026), 40% projektów na React Native używa SectionList do organizacji strukturyzowanych danych. W przeciwieństwie do ręcznego grupowania wewnątrz FlatList, SectionList zapewnia wbudowaną obsługę sekcji.
SectionList jest stosowany w listach kontaktów z indeksem alfabetycznym, gdzie każda litera to osobna sekcja. W e-commerce komponent grupuje produkty według kategorii lub marek. W aplikacjach do notatek — według dat lub tagów. W ustawieniach — według działów (Podstawowe, Bezpieczeństwo, Powiadomienia).
Według badań użycia React Native (Meta, 2026), SectionList jest najbardziej wydajny przy 5–50 sekcjach z 3–20 elementami w każdej. Przy mniejszej liczbie sekcji łatwiej użyć FlatList z grupowaniem przez ListHeaderComponent. Przy większej — pojawiają się problemy z wydajnością z powodu dużej liczby nagłówków.
SectionList Data przyjmuje tablicę obiektów Section, z których każdy zawiera title (nagłówek sekcji) i data (tablica elementów). Dodatkowo można przekazywać key i renderItem dla każdej sekcji osobno, nadpisując ogólny renderItem.
const sections = [
{
title: 'React Native',
data: ['FlatList', 'SectionList', 'VirtualizedList'],
},
{
title: 'React',
data: ['Hooks', 'Context', 'Suspense'],
},
{
title: 'Android',
data: ['Activity', 'Fragment', 'ViewModel'],
},
];renderSectionHeader — funkcja renderowania nagłówka sekcji, otrzymująca obiekt sekcji. renderItem — funkcja renderowania elementu, analogiczna do FlatList. Komponent obsługuje również renderSectionFooter dla dolnej części każdej sekcji.
<SectionList
sections={sections}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => (
<View style={styles.item}>
<Text>{item}</Text>
</View>
)}
renderSectionHeader={({ section }) => (
<View style={styles.sectionHeader}>
<Text style={styles.sectionTitle}>{section.title}</Text>
</View>
)}
/>Sticky headers — kluczowa cecha SectionList. Gdy użytkownik przewija, nagłówek bieżącej sekcji przykleja się do górnej krawędzi ekranu, aż sekcja całkowicie się nie przewinie. Daje to użytkownikowi stały kontekst o bieżącej kategorii.
Tryb sticky jest włączony domyślnie. Aby wyłączyć, użyj stickySectionHeadersEnabled={false}. Na iOS nagłówki przyklejają się z natywną animacją, na Androidzie — przez JS. Dla indeksów alfabetycznych wygodnie jest dodać panel boczny z literami do szybkiej nawigacji.
const ContactsList = () => {
const sectionListRef = React.useRef(null);
const scrollToSection = (index) => {
sectionListRef.current?.scrollToLocation({
sectionIndex: index,
itemIndex: 0,
viewPosition: 0,
});
};
return (
<View>
<SectionList
ref={sectionListRef}
sections={sections}
keyExtractor={(item) => item.id}
renderItem={renderItem}
renderSectionHeader={renderSectionHeader}
onViewableItemsChanged={onViewableItemsChanged}
/>
</View>
);
};scrollToLocation — metoda do programowej nawigacji do dowolnej sekcji. Przyjmuje sectionIndex, itemIndex i viewPosition (0 — początek, 0.5 — środek, 1 — koniec). Łącząc z bocznym indeksem alfabetycznym, można zaimplementować szybką nawigację jak w standardowych kontaktach iOS.
Optymalizacja SectionList opiera się na tych samych zasadach co optymalizacja FlatList, z dodatkowymi niuansami związanymi z sekcjami. Każdy nagłówek sekcji to dodatkowy View, który jest renderowany i przerenderowywany podczas przewijania. Przy 50+ sekcjach nagłówki mogą spowolnić przewijanie.
Używaj React.memo dla renderSectionHeader i renderItem, aby uniknąć zbędnych przerenderowań. Jeśli sekcje nie zmieniają się dynamicznie, rozważ useMemo dla tablicy sections. Dla bardzo dużych list łącz SectionList z getItemLayout, podając stałą wysokość nagłówków i elementów.
| Technika optymalizacji | Opis | Efekt |
|---|---|---|
| React.memo | Memoizacja komponentów nagłówków i elementów | Zmniejsza liczbę przerenderowań podczas przewijania |
| getItemLayout | Stała wysokość nagłówka + elementu | Usuwa pomiar, przyspiesza przewijanie do indexu |
| maxToRenderPerBatch | Ograniczenie elementów w partii | Zapobiega opóźnieniom przy szybkim przewijaniu |
| windowSize | Zmniejszenie do 5–10 dla dużych list | Zmniejsza liczbę jednocześnie renderowanych elementów |
Wybór między SectionList a FlatList zależy od struktury danych. Jeśli dane to płaska tablica — użyj FlatList. Jeśli dane naturalnie grupują się w kategorie z nagłówkami — SectionList. Nie używaj SectionList dla jednej sekcji — FlatList poradzi sobie wydajniej.
Różnica w wydajności jest minimalna przy tej samej liczbie elementów. SectionList dodaje narzut na renderowanie nagłówków, ale ten narzut jest uzasadniony, gdy nagłówki niosą znaczenie. Jeśli nagłówki nie są potrzebne — FlatList z ListHeaderComponent do imitacji sekcji będzie szybszy.
Używaj SectionList, gdy: dane są domyślnie zgrupowane (kontakty według liter), potrzebne są sticky headers, nagłówki sekcji zawierają elementy interaktywne (przyciski, checkboxy). Używaj FlatList, gdy: dane są płaskie, grupowanie zmienia się dynamicznie, kategorii jest więcej niż 50, a nagłówki są jednolite.
SectionList z indeksem alfabetycznym — klasyczny przykład użycia. Implementacja obejmuje panel boczny z literami i scrollToLocation do skoku do sekcji. Poniżej pełna implementacja listy kontaktów z nawigacją alfabetyczną.
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
const AlphabetContacts = () => {
const ref = React.useRef(null);
const sections = React.useMemo(() =>
ALPHABET.map(letter => ({
title: letter,
data: contacts.filter(c => c.name.startsWith(letter)),
})).filter(s => s.data.length > 0),
[]);
return (
<View style={styles.container}>
<SectionList
ref={ref}
sections={sections}
keyExtractor={item => item.id}
renderItem={renderContact}
renderSectionHeader={renderHeader}
getItemLayout={getItemLayout}
/>
<View style={styles.sidebar}>
{ALPHABET.map(letter => (
<Text
key={letter}
onPress={() => scrollToSection(letter)}
>{letter}</Text>
))}
</View>
</View>
);
};Ważne: przy dynamicznym filtrowaniu sekcji używaj useMemo do stabilizacji tablicy. Bez memoizacji SectionList będzie odtwarzać wszystkie komórki przy każdej zmianie filtra, co doprowadzi do utraty przewijania i stanu zagnieżdżonych komponentów.
Często zadawane pytania
Tak, SectionList obsługuje dynamiczne zmiany sekcji. Przy zmianie tablicy sections komponent przerenderuje tylko zmienione sekcje. Do stabilnej pracy używaj key dla każdej sekcji i owijaj komponenty w React.memo.
Filtruj tablicę sections przed przekazaniem: odfiltruj sekcje z pustym data. Jeśli dane pochodzą z API, filtruj w useMemo. Dla pustego stanu całej listy użyj ListEmptyComponent.
Sticky headers na Androidzie są domyślnie włączone, ale mogą nie działać przy konflikcie z nestedScrollEnabled. Upewnij się, że SectionList nie jest zagnieżdżony w ScrollView. Na Android 12+ sticky headers działają przez natywny mechanizm, na starszych wersjach — przez JS.
SectionList nie zapewnia wbudowanej animacji zmiany sticky header. Do własnej animacji śledź onViewableItemsChanged i animuj zmianę nagłówka przez Animated API lub react-native-reanimated.
Tak, każda sekcja dodaje nagłówek do DOM. Przy 100+ sekcjach wydajność SectionList spada z powodu dużej liczby nagłówków. Rozwiązanie: zgrupuj dane w 10–20 logicznych sekcji lub użyj FlatList z własnym grupowaniem.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również