FlatList: nó là gì, API và tối ưu hóa trong React Native

Tác giả: IT Sectr Đã đăng: 2026-07-05 Thời gian đọc: 10 phút

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à thành phần danh sách được ảo hóa, chỉ hiển thị các phần tử hiển thị và tái sử dụng chúng khi cuộn
  • Hiệu suất đạt được nhờ hiển thị theo cửa sổ — các phần tử ngoài màn hình không được tạo
  • API bao gồm renderItem, keyExtractor, ItemSeparatorComponent, ListHeaderComponent và ListFooterComponent
  • Danh sách ngang được cấu hình qua cờ horizontal và thay đổi hướng cuộn sang trục X
  • Tối ưu hóa yêu cầu cấu hình đúng keyExtractor, useMemo cho dữ liệu và getItemLayout cho kích thước cố định

FlatList là gì?

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.

Lịch sử và vị trí trong hệ sinh thái

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.

Cách thức hoạt động của ảo hóa FlatList

Ả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 địnhMô tả
windowSize21Số trang để hiển thị (1 trang = chiều cao màn hình)
initialNumToRender10Số phần tử khi hiển thị lần đầu
maxToRenderPerBatch10Số phần tử tối đa được hiển thị mỗi đợt
removeClippedSubviewsfalseXó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 và các props chính của FlatList

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ử.

js
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ử, ListHeaderComponentListFooterComponent 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.

js
const styles = StyleSheet.create({
  item: {
    padding: 16,
    backgroundColor: '#fff',
    borderBottomWidth: 1,
    borderBottomColor: '#e0e0e0',
  },
  separator: {
    height: 1,
    backgroundColor: '#ccc',
  },
});

Tối ưu hóa hiệu suất FlatList

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ử.

getItemLayout cho chiều cao cố định

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ể.

js
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.

Danh sách ngang và băng chuyền

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 snapToIntervalsnapToAlignment để 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.

js
<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 và cuộn vô hạn

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.

js
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 khác ScrollView như thế nào?

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ử.

Làm thế nào để sửa hiện tượng nhấp nháy khi cập nhật dữ liệu FlatList?

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.

Tại sao FlatList không cuộn được bên trong một scroll view khác?

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.

Làm thế nào để tạo hiệu ứng xuất hiện cho phần tử FlatList?

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à gì và nó liên quan thế nào đến FlatList?

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

  • FlatList là thành phần chính của React Native cho danh sách hiệu suất cao với ảo hóa tự động và tái sử dụng ô
  • Ảo hóa chỉ hiển thị các phần tử hiển thị qua windowSize và initialNumToRender, tiết kiệm bộ nhớ trên tập dữ liệu lớn
  • Props bắt buộc: data, renderItem và keyExtractor — đảm bảo hoạt động chính xác của danh sách
  • getItemLayout tăng tốc cuộn cho các phần tử có chiều cao cố định, loại bỏ đo lường động
  • Danh sách ngang và băng chuyền được cấu hình qua horizontal và snapToInterval để cuộn từng bước
  • Kéo để làm mới và onEndReached triển khai tải vô hạn với bảo vệ chống gọi lặp lại
  • React.memo và useCallback là bắt buộc cho renderItem — nếu không có, mỗi lần cuộn sẽ kích hoạt hiển thị lại tất cả phần 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.

Thảo luận dự án

Đọc thêm