Giới thiệu
Trong các ứng dụng di động React Native, FlatList là thành phần danh sách được sử dụng phổ biến vì khả năng render lazy và hỗ trợ dữ liệu lớn. Tuy nhiên, khi danh sách chứa hàng nghìn mục, hiệu suất có thể giảm đáng kể nếu không áp dụng các kỹ thuật tối ưu. Bài viết này sẽ hướng dẫn chi tiết cách tối ưu FlatList khi viết bằng TypeScript, giúp giảm thời gian render, giảm tiêu thụ bộ nhớ và mang lại trải nghiệm mượt mà cho người dùng.
Nguyên nhân thường gặp gây chậm
Một số yếu tố thường làm FlatList chậm:
- Render lại toàn bộ danh sách mỗi khi state thay đổi.
- Không cung cấp
keyExtractorđúng, dẫn tới việc React phải tính toán lại cây DOM. - Không xác định chiều cao cố định của mỗi mục, khiến
VirtualizedListphải đo lại kích thước mỗi lần scroll. - Số lượng mục render đồng thời quá lớn (
initialNumToRender,maxToRenderPerBatch).
Các kỹ thuật tối ưu quan trọng
1. Sử dụng keyExtractor ổn định
Đảm bảo mỗi mục có key duy nhất và không thay đổi trong suốt vòng đời của danh sách. Thông thường, sử dụng id từ dữ liệu.
2. Xác định chiều cao cố định với getItemLayout
Khi chiều cao của mục là cố định, FlatList có thể tính toán vị trí của các mục mà không cần đo lại. Điều này giảm đáng kể thời gian tính toán khi scroll.
3. Memo hoá hàm render
Sử dụng React.memo cho hàm renderItem để tránh render lại các mục không thay đổi.
4. Điều chỉnh các tham số render
Các thuộc tính initialNumToRender, maxToRenderPerBatch và windowSize giúp kiểm soát số mục được render đồng thời. Giá trị phù hợp tùy thuộc vào độ phức tạp UI và khả năng của thiết bị.
5. Kiểm tra hiệu suất với Flipper
Công cụ Flipper cung cấp tab Performance để đo thời gian render và memory usage của FlatList. Hãy đo sau mỗi thay đổi để xác nhận cải thiện.
Một ví dụ thực tế
Dưới đây là đoạn code tối ưu một FlatList hiển thị 1000 mục, sử dụng TypeScript và các kỹ thuật đã nêu.
import React, { memo } from 'react';
import { FlatList, View, Text, StyleSheet, ListRenderItemInfo } from 'react-native';
type Item = {
id: string;
title: string;
};
const DATA: Item[] = Array.from({ length: 1000 }, (_, i) => ({
id: i.toString(),
title: `Item ${i + 1}`,
}));
const renderItem = memo(({ item }: ListRenderItemInfo) => (
<View style={styles.item}>
<Text>{item.title}</Text>
</View>
));
export default function OptimizedFlatList() {
return (
<FlatList
data={DATA}
keyExtractor={item => item.id}
renderItem={renderItem}
initialNumToRender={10}
maxToRenderPerBatch={5}
windowSize={5}
getItemLayout={(_, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
/>
);
}
const ITEM_HEIGHT = 50;
const styles = StyleSheet.create({
item: {
height: ITEM_HEIGHT,
justifyContent: 'center',
paddingHorizontal: 16,
borderBottomWidth: 1,
borderColor: '#ccc',
},
});
Kết luận
Bằng cách áp dụng keyExtractor ổn định, xác định chiều cao cố định qua getItemLayout, memo hoá hàm render và tinh chỉnh các tham số render, FlatList trong React Native sẽ hoạt động nhanh hơn đáng kể, ngay cả khi dữ liệu lên tới hàng ngàn mục. Đừng quên đo lại hiệu suất bằng Flipper để xác nhận kết quả.
Để nắm vững toàn bộ quy trình phát triển ứng dụng di động chuyên nghiệp, bạn có thể Tham khảo khóa học "Lập trình App Mobile với React Native + TypeScript" tại đây.








