SectionList** là component hiển thị danh sách có phân nhóm (section), hỗ trợ header/footer cho từng section và toàn bộ list. Phù hợp cho danh sách băm chữ cái, phân loại sản phẩm, lịch sử theo ngày...
Import
import { SectionList, Text, View, StyleSheet } from 'react-native';
Cú pháp cơ bản
<SectionList
sections={data}
renderItem={({ item }) => {item} }
renderSectionHeader={({ section: { title } }) => {title} }
keyExtractor={(item, index) => item + index}
/>
Các props quan trọng
| Prop | Bắt buộc | Mô tả |
|---|---|---|
sections | Có | Mảng object: [{ title: 'Header', data: [...] }, ...] |
renderItem | Có | Function render item: ({ item, index, section, separators }) => ReactElement |
renderSectionHeader | Không | Render header cho từng section. iOS: header dính (sticky) mặc định. |
renderSectionFooter | Không | Render footer cho từng section. |
keyExtractor | Không | Tạo key duy nhất: (item, index) => string. Mặc định dùng index. |
stickySectionHeadersEnabled | Không | true: header dính ở đầu khi cuộn (iOS mặc định true). |
ListHeaderComponent | Không | Header của cả list. |
ListFooterComponent | Không | Footer của cả list. |
refreshing / onRefresh | Không | Hỗ trợ pull-to-refresh. |
onEndReached / onEndReachedThreshold | Không | Infinite scroll (load more). |
initialNumToRender | Không | Số item render lần đầu (mặc định 10). |
getItemLayout | Không | Tối ưu hiệu suất cho item chiều cao cố định. |
Ví dụ 1: SectionList cơ bản
import React from 'react';
import { SectionList, Text, View, StyleSheet } from 'react-native';
export default class App extends React.Component {
constructor() {
super();
this.state = {
data: [
{
title: 'JavaScript Frameworks',
data: ['Angular', 'ReactJS', 'VueJS', 'ReactNative'],
},
{
title: 'PHP Frameworks',
data: ['Laravel', 'CodeIgniter', 'CakePHP', 'Symfony'],
},
],
};
}
renderItem = ({ item }) => (
{item}
);
render() {
return (
item + index}
renderSectionHeader={({ section: { title } }) => (
{title}
)}
/>
);
}
}
const styles = StyleSheet.create({
container: { flex: 1, marginTop: 20, marginHorizontal: 16 },
item: { backgroundColor: '#ccc2ff', padding: 20, marginVertical: 8 },
header: { fontSize: 22, fontWeight: 'bold', backgroundColor: '#fff', paddingVertical: 10 },
});
Ví dụ 2: Bật stickySectionHeadersEnabled (header dính)
Thêm prop stickySectionHeadersEnabled={true} (mặc định true trên iOS, false trên Android). Khi cuộn, header section sẽ "dính" ở đỉnh màn hình cho đến khi header section tiếp theo đẩy nó lên.
item + index} renderSectionHeader={({ section: { title } }) => ( {title} )} stickySectionHeadersEnabled={true} />
Ví dụ 3: SectionList với object phức tạp & Footer
const data = [
{
title: 'Hôm nay',
data: [
{ id: 1, name: 'Meeting 10h', time: '10:00' },
{ id: 2, name: 'Lunch', time: '12:30' },
],
},
{
title: 'Ngày mai',
data: [
{ id: 3, name: 'Call client', time: '09:00' },
],
},
];
(
{item.name}
{item.time}
)}
renderSectionHeader={({ section: { title } }) => (
{title}
)}
renderSectionFooter={() => }
keyExtractor={item => item.id.toString()}
ListHeaderComponent={() => Lịch làm việc }
/>
Hiệu suất & Tối ưu
- Dùng
getItemLayoutnếu item có chiều cao cố định (bỏ qua đo lường layout). initialNumToRender: Chỉ render item đầu tiên hiển thị.maxToRenderPerBatch,windowSize: Tinh chỉnh batch rendering.- Tránh inline function trong renderItem (tạo function ngoài hoặc dùng
useCallback). - Dùng
PureComponenthoặcReact.memocho item component.
SectionList vs FlatList
| Đặc điểm | FlatList | SectionList |
|---|---|---|
| Cấu trúc data | Mảng phẳng [] | Mảng section [{ title, data: [] }] |
| Header section | Không có sẵn | Có sẵn (renderSectionHeader) |
| Sticky header | Cần custom | Hỗ trợ sẵn (stickySectionHeadersEnabled) |
| Phù hợp | Danh sách đơn giản | Danh sách có nhóm, phân loại |