FlatList là thành phần chính của React Native để hiển thị danh sách hiệu suất cao với ảo hóa phần tử. Không giống như ScrollView, FlatList chỉ hiển thị các phần tử hiển thị trên màn hình, tiết kiệm bộ nhớ và CPU. Thành phần hỗ trợ cuộn ngang và dọc, kéo để làm mới và tải vô hạn. Đọc thêm về kiến trúc danh sách trong tài liệu của Meta.
Những điểm chính
FlatList là một thành phần React Native triển khai danh sách được ảo hóa với hiệu suất hiển thị cao cho các tập dữ liệu lớn. Thành phần được xây dựng trên VirtualizedList và cung cấp API khai báo để tạo danh sách phẳng ở mọi độ phức tạp.
FlatList được giới thiệu trong React Native 0.43 để thay thế ListView cũ. Theo Meta (2026), FlatList được sử dụng trong 85% ứng dụng React Native làm việc với danh sách. Thành phần hỗ trợ tất cả các tình huống phổ biến: danh bạ, bảng tin, danh mục sản phẩm và trò chuyện.
Trước FlatList, các nhà phát triển sử dụng ListView, yêu cầu cấu hình thủ công việc tái sử dụng ô. FlatList đã tự động hóa quy trình này bằng cách triển khai hiển thị theo cửa sổ tương tự RecyclerView trong Android (2014) và UICollectionView trong iOS (2012). Trong các dự án hiện đại, FlatList là tiêu chuẩn thực tế cho mọi danh sách.
Ảo hóa FlatList là cơ chế trong đó thành phần chỉ hiển thị các phần tử nằm trong vùng hiển thị của màn hình, cộng với một bộ đệm nhỏ ở mỗi bên. Các phần tử còn lại không được tạo trong DOM, tiết kiệm bộ nhớ và tăng tốc hiển thị.
Khi cuộn, FlatList tái sử dụng các ô View đã được tạo, thay thế dữ liệu của chúng. Điều này ngăn việc tạo hàng nghìn View cho danh sách 10.000 phần tử. Kích thước bộ đệm mặc định là 10 phần tử phía trên và phía dưới vùng hiển thị, nhưng có thể cấu hình qua windowSize.
| Tham số | Mặc định | Mô tả |
|---|---|---|
| windowSize | 21 | Số trang để hiển thị (1 trang = chiều cao màn hình) |
| initialNumToRender | 10 | Số phần tử khi hiển thị lần đầu |
| maxToRenderPerBatch | 10 | Số phần tử tối đa được hiển thị mỗi đợt |
| removeClippedSubviews | false | Xóa View ngoài màn hình khỏi hệ thống phân cấp |
Cấu hình tối ưu các tham số này cho phép cân bằng giữa độ mượt khi cuộn và mức tiêu thụ bộ nhớ. Đối với danh sách có phần tử lớn, nên giảm windowSize xuống 5-7.
API FlatList bao gồm một tập hợp các props để cấu hình hiển thị và hành vi của danh sách. Hai props bắt buộc là data (mảng dữ liệu) và renderItem (hàm hiển thị phần tử). keyExtractor cải thiện hiệu suất bằng cách cung cấp khóa duy nhất cho mỗi phần tử.
import React from 'react';
import { FlatList, View, Text, StyleSheet } from 'react-native';
const App = () => {
const data = Array.from({ length: 100 }, (_, i) => ({
id: i.toString(),
title: `Item #${i + 1}`,
}));
return (
<FlatList
data={data}
renderItem={({ item }) => (
<View style={styles.item}>
<Text>{item.title}</Text>
</View>
)}
keyExtractor={item => item.id}
ItemSeparatorComponent={() => <View style={styles.separator} />}
/>
);
};ItemSeparatorComponent thêm dấu phân cách giữa các phần tử, ListHeaderComponent và ListFooterComponent thêm đầu trang và chân trang cho danh sách. Điều này cho phép tạo bố cục phức tạp mà không cần wrapper bổ sung.
const styles = StyleSheet.create({
item: {
padding: 16,
backgroundColor: '#fff',
borderBottomWidth: 1,
borderBottomColor: '#e0e0e0',
},
separator: {
height: 1,
backgroundColor: '#ccc',
},
});Tối ưu hóa FlatList rất quan trọng đối với các ứng dụng có hàng trăm và hàng nghìn phần tử. Nếu không cấu hình đúng, danh sách có thể bị chậm khi cuộn, tiêu tốn bộ nhớ quá mức và gây treo trên các thiết bị yếu.
Quy tắc đầu tiên là sử dụng keyExtractor với các định danh duy nhất và ổn định. Sử dụng chỉ mục làm khóa dẫn đến việc tái sử dụng ô không chính xác và lỗi trạng thái. Quy tắc thứ hai là bọc renderItem trong useCallback và sử dụng React.memo cho thành phần phần tử.
Nếu tất cả các phần tử có cùng chiều cao, getItemLayout cho phép FlatList tính toán vị trí cuộn mà không cần đo lường thành phần. Điều này mang lại cải thiện hiệu suất đáng kể, đặc biệt khi cuộn đến một chỉ mục cụ thể.
const ITEM_HEIGHT = 80;
const getItemLayout = (data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
});
<FlatList
data={data}
getItemLayout={getItemLayout}
renderItem={renderItem}
/FlatList>useMemo cho dữ liệu ngăn chặn việc hiển thị lại không cần thiết. Nếu dữ liệu đến từ API, hãy chuyển đổi nó một lần và lưu vào bộ nhớ đệm. Sử dụng React.memo cho thành phần phần tử để tránh hiển thị các phần tử không thay đổi.
FlatList ngang được tạo bằng cách thêm prop horizontal={true}. Danh sách thay đổi hướng cuộn sang trục X, thuận tiện cho băng chuyền sản phẩm, thư viện ảnh và menu ngang.
Ở chế độ ngang, điều quan trọng là cấu hình đúng snapToInterval và snapToAlignment để cuộn từng bước như băng chuyền gốc. Thành phần tự động xử lý đà và thả ngón tay, dừng lại ở phần tử gần nhất.
<FlatList
horizontal
data={images}
renderItem={renderItem}
keyExtractor={item => item.id}
showsHorizontalScrollIndicator={false}
snapToInterval={CARD_WIDTH + GAP}
snapToAlignment="start"
decelerationRate="fast"
pagingEnabled
onViewableItemsChanged={onViewableItemsChanged}
/>onViewableItemsChanged là callback được kích hoạt khi các phần tử hiển thị thay đổi. Nó được sử dụng cho phân tích, tải ảnh chậm và kích hoạt video chỉ cho các thẻ hiển thị.
Kéo để làm mới trong FlatList được triển khai qua các props refreshing và onRefresh, hoạt động cùng với trạng thái tải. Khi kéo danh sách xuống, onRefresh được gọi, và cờ refreshing chặn các lệnh gọi lặp lại.
Cuộn vô hạn được cấu hình qua onEndReached — một callback được kích hoạt khi đến gần cuối danh sách. onEndReachedThreshold xác định bao nhiêu phần tử trước khi kết thúc thì sự kiện được kích hoạt. Phân trang dựa trên con trỏ thường được sử dụng.
const ListWithPagination = () => {
const [data, setData] = React.useState([]);
const [page, setPage] = React.useState(1);
const [refreshing, setRefreshing] = React.useState(false);
const loadMore = React.useCallback(async () => {
const newData = await fetchPage(page);
setData(prev => [...prev, ...newData]);
setPage(p => p + 1);
}, [page]);
return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item.id}
refreshing={refreshing}
onRefresh={loadMore}
onEndReached={loadMore}
onEndReachedThreshold={0.5}
/>
);
};Quan trọng: onEndReached có thể được gọi nhiều lần. Thêm cờ isLoading để chặn các yêu cầu lặp lại cho đến khi yêu cầu trước đó hoàn tất. Sử dụng ActivityIndicator trong ListFooterComponent để chỉ báo tải.
Câu hỏi thường gặp
FlatList sử dụng ảo hóa — chỉ hiển thị các phần tử hiển thị, tiết kiệm bộ nhớ với tập dữ liệu lớn. ScrollView hiển thị tất cả các phần tử con cùng một lúc, chỉ phù hợp cho danh sách nhỏ 20-30 phần tử. FlatList tối ưu cho 100+ phần tử.
Nhấp nháy xảy ra khi tham chiếu đến mảng dữ liệu thay đổi. Sử dụng extraData truyền phụ thuộc, hoặc bọc renderItem trong React.memo. Để kiểm soát hoàn toàn, sử dụng useMemo để ổn định các tham chiếu dữ liệu.
FlatList không được thiết kế để lồng bên trong ScrollView do xung đột cử chỉ. Giải pháp: sử dụng FlatList với nestedScrollEnabled (Android), SectionList cho các phần, hoặc di chuyển cuộn ngoài vào FlatList qua ListHeaderComponent.
Sử dụng Animated API bên trong renderItem với độ trễ dựa trên chỉ mục. Khi cuộn, sử dụng onViewableItemsChanged để kích hoạt hoạt ảnh. Các thư viện react-native-reanimated và react-native-lottie đơn giản hóa việc tạo hoạt ảnh xuất hiện phức tạp.
VirtualizedList là thành phần ảo hóa cơ sở mà FlatList và SectionList được xây dựng trên đó. FlatList là một wrapper của VirtualizedList với API đơn giản hóa cho danh sách phẳng. VirtualizedList cung cấp kiểm soát cấp thấp hơn nhưng hiếm khi được sử dụng trực tiếp.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm