Một danh sách cuộn giật không nhất thiết được sửa bằng cách tăng windowSize. Có khi mỗi hàng đang dựng ảnh lớn, nhận props mới liên tục hoặc làm phép tính không cần thiết trong lúc render.
Bài này tiếp nối hướng dẫn FlatList cơ bản. Ví dụ dùng TypeScript và các API FlatList thông dụng, đối chiếu tài liệu React Native ngày 21/10/2026. Các con số trong code là cấu hình minh họa cho hàng có chiều cao cố định, không phải kết quả benchmark hoặc bộ giá trị tối ưu cho mọi app.
1. Xác định biểu hiện trước khi thay cấu hình
Ghi lại thiết bị, bản build và thao tác gây vấn đề. Phân biệt ít nhất ba hiện tượng: xuất hiện khoảng trống khi cuộn nhanh, thao tác bấm phản hồi chậm và bộ nhớ tăng cao.
Tài liệu tối ưu FlatList mô tả sự đánh đổi giữa phạm vi giữ item, tần suất render và khả năng phản hồi. Một cấu hình giảm khoảng trống có thể khiến công việc JavaScript theo mỗi đợt dài hơn. Bạn cần chọn theo vấn đề đã quan sát, không chép đồng loạt nhiều props từ một đoạn mẫu.
2. Làm cho mỗi hàng đơn giản và nhận diện ổn định
Trước hết, bỏ phép xử lý nặng khỏi render item và dùng ID ổn định cho key. Khi một bản ghi đổi vị trí, key theo index không mô tả được cùng một thực thể dữ liệu tốt như ID của nó.
Ví dụ dưới đây chỉ hiển thị tiêu đề và tác giả. Nó không tải ảnh hoặc gọi mạng nên giúp bạn kiểm tra riêng phần danh sách:
import { memo } from 'react';
import {
FlatList,
StyleSheet,
Text,
View,
type ListRenderItemInfo,
} from 'react-native';
type Article = {
id: string;
title: string;
author: string;
};
const ROW_HEIGHT = 72;
const SEPARATOR_HEIGHT = 1;
const ArticleRow = memo(function ArticleRow({
title,
author,
}: Pick<Article, 'title' | 'author'>) {
return (
<View style={styles.row}>
<Text numberOfLines={1}>{title}</Text>
<Text numberOfLines={1}>{author}</Text>
</View>
);
});
function Separator() {
return <View style={styles.separator} />;
}
function renderArticle({ item }: ListRenderItemInfo<Article>) {
return <ArticleRow title={item.title} author={item.author} />;
}
export function ArticleList({ articles }: { articles: Article[] }) {
return (
<FlatList
data={articles}
keyExtractor={item => item.id}
renderItem={renderArticle}
ItemSeparatorComponent={Separator}
getItemLayout={(_, index) => ({
length: ROW_HEIGHT,
offset: (ROW_HEIGHT + SEPARATOR_HEIGHT) * index,
index,
})}
/>
);
}
const styles = StyleSheet.create({
row: {
height: ROW_HEIGHT,
paddingHorizontal: 16,
justifyContent: 'center',
},
separator: {
height: SEPARATOR_HEIGHT,
backgroundColor: '#e5e7eb',
},
});
Trong ví dụ, item không nhận object được tạo lại cho style hoặc callback mới từ component cha. memo giúp bỏ qua một số render khi props không thay đổi; nó không chặn cập nhật state hoặc context bên trong component. React cũng lưu ý dự án dùng React Compiler có thể ít cần memoization thủ công hơn. Xem React memo.
3. Chỉ dùng getItemLayout khi biết đúng kích thước
Tài liệu FlatList yêu cầu tính cả kích thước separator trong offset. Vì vậy, hàng 72 và separator 1 có bước dịch chuyển là 73, không phải 72.
Điều kiện của ví dụ là mọi hàng giữ chiều cao 72 và không có header hay padding dọc thay đổi phép tính. Nếu thiết kế cho phép tiêu đề nhiều dòng hoặc chữ lớn làm hàng cao hơn, bỏ tối ưu này hoặc thay cách tính phù hợp. Không ép chiều cao để che một lỗi đo; hãy kiểm tra khả năng đọc với cỡ chữ lớn trước khi dùng hàng cố định.
4. Đo lại trước khi chỉnh batch và window
Sau khi làm nhẹ item, giữ một đường cuộn và bộ dữ liệu cố định để so sánh trước/sau. Kiểm tra trên thiết bị gần với nhóm người dùng mục tiêu, trong bản build dùng để đánh giá hiệu năng. Không suy từ một lần cuộn trên máy phát triển mạnh rằng mọi thiết bị đều đã ổn.
Nếu vẫn có khoảng trống, thử một thay đổi cấu hình mỗi lần. Khi tăng lượng item mỗi batch, quan sát cả độ trống lẫn phản hồi khi bấm. Khi giảm phạm vi giữ item, quan sát bộ nhớ và khả năng xuất hiện vùng chưa render. Ghi kết quả thay vì chỉ giữ cảm giác “mượt hơn”.
Lỗi thường gặp
- Thêm trạng thái chọn nhưng hàng không đổi: kiểm tra dữ liệu đầu vào và
extraDatakhi render phụ thuộc trạng thái ngoàidata; đồng thời truyền props thực sự thay đổi cho hàng đã memo. - Cuộn đến sai vị trí: kiểm tra chiều cao hàng, separator, header và spacing trước khi đổi công thức offset.
- Gắn memo nhưng vẫn render nhiều: tìm object, mảng hoặc hàm được tạo mới; sau đó xác định render đó có thật sự tốn chi phí không.
Tối ưu hữu ích bắt đầu từ một biểu hiện có thể tái hiện. Item nhẹ, dữ liệu có định danh ổn định và phép đo đúng thường giúp bạn quyết định cần thay đổi props nào, thay vì biến cấu hình FlatList thành một bộ số khó giải thích.





