FlatList: What It Is, API and Optimization in React Native

Author: IT Sectr Published: 2026-07-05 Reading time: 10 min

FlatList is the main React Native component for displaying high-performance lists with element virtualization. Unlike ScrollView, FlatList renders only the visible screen elements, saving memory and CPU. The component supports horizontal and vertical scrolling, pull-to-refresh, and infinite loading. Read more about list architecture in Meta's documentation.

Key Takeaways

  • FlatList is a virtualized list component that renders only visible elements and reuses them during scrolling
  • Performance is achieved through windowed rendering — elements outside the screen are not created
  • API includes renderItem, keyExtractor, ItemSeparatorComponent, ListHeaderComponent, and ListFooterComponent
  • Horizontal lists are configured via the horizontal flag, changing the scroll direction to the X axis
  • Optimization requires proper configuration of keyExtractor, useMemo for data, and getItemLayout for fixed sizes

What is FlatList?

FlatList is a React Native component that implements a virtualized list with high-performance rendering of large data sets. The component is built on top of VirtualizedList and provides a declarative API for creating flat lists of any complexity.

FlatList was introduced in React Native 0.43 as a replacement for the deprecated ListView. According to Meta (2026), FlatList is used in 85% of React Native applications that work with lists. The component supports all common scenarios: contacts, news feeds, product catalogs, and chats.

History and Place in the Ecosystem

Before FlatList, developers used ListView, which required manual cell reuse configuration. FlatList automated this process by implementing windowed rendering similar to RecyclerView in Android (2014) and UICollectionView in iOS (2012). In modern projects, FlatList is the de facto standard for any list implementation.

How FlatList Virtualization Works

FlatList virtualization is a mechanism where the component renders only the elements that fall within the visible screen area, plus a small buffer on each side. The remaining elements are not created in the DOM, saving memory and speeding up rendering.

When scrolling, FlatList reuses already created View cells, replacing their data. This prevents creating thousands of Views for a list of 10,000 elements. The default buffer size is 10 elements above and below the visible area, but it is configurable via windowSize.

ParameterDefaultDescription
windowSize21Number of pages to render (1 page = screen height)
initialNumToRender10Number of elements on the first render
maxToRenderPerBatch10Maximum elements rendered per batch
removeClippedSubviewsfalseRemove Views outside the screen from the hierarchy

Optimal configuration of these parameters allows balancing between scroll smoothness and memory consumption. For lists with large elements, it is recommended to reduce windowSize to 5-7.

FlatList API and Key Props

FlatList API includes a set of props for configuring the list display and behavior. The two required props are data (data array) and renderItem (element rendering function). keyExtractor improves performance by providing a unique key for each element.

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 adds a separator between elements, ListHeaderComponent and ListFooterComponent add header and footer to the list. This allows creating complex layouts without additional wrappers.

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

FlatList Performance Optimization

FlatList optimization is critical for applications with hundreds and thousands of elements. Without proper configuration, the list may lag during scrolling, consume excessive memory, and cause crashes on low-end devices.

The first rule is to use keyExtractor with unique and stable identifiers. Using indices as keys leads to incorrect cell reuse and state bugs. The second rule is to wrap renderItem in useCallback and use React.memo for the item component.

getItemLayout for Fixed Height

If all elements have the same height, getItemLayout allows FlatList to calculate the scroll position without measuring components. This provides a significant performance boost, especially when scrolling to a specific index.

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 for data prevents unnecessary re-renders. If data comes from an API, transform it once and cache it. Use React.memo for the item component to avoid rendering unchanged elements.

Horizontal Lists and Carousels

Horizontal FlatList is created by adding the prop horizontal={true}. The list changes the scroll direction to the X axis, which is convenient for product carousels, image galleries, and horizontal menus.

In horizontal mode, it is important to correctly configure snapToInterval and snapToAlignment for step-by-step scrolling like in native carousels. The component automatically handles momentum and finger release, stopping at the nearest element.

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 is a callback triggered when visible elements change. It is used for analytics, lazy image loading, and activating videos only for visible cards.

Pull-to-Refresh and Infinite Scroll

Pull-to-refresh in FlatList is implemented via the refreshing and onRefresh props, working together with a loading state. When pulling the list down, onRefresh is called, and the refreshing flag blocks repeated calls.

Infinite scroll is configured via onEndReached — a callback triggered when approaching the end of the list. onEndReachedThreshold determines how many elements before the end the event fires. Cursor-based pagination is typically used.

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}
    />
  );
};

Important: onEndReached may be called multiple times. Add an isLoading flag to block repeated requests until the previous one completes. Use ActivityIndicator in ListFooterComponent to indicate loading.

Frequently Asked Questions

How does FlatList differ from ScrollView?

FlatList uses virtualization — it renders only visible elements, saving memory with large data sets. ScrollView renders all children at once, suitable only for small lists of 20-30 elements. FlatList is optimal for 100+ elements.

How to fix flashing when updating FlatList data?

Flashing occurs when the reference to the data array changes. Use extraData passing the dependency, or wrap renderItem in React.memo. For full control, use useMemo to stabilize data references.

Why does FlatList not scroll inside another scroll view?

FlatList is not designed to be nested inside ScrollView due to gesture conflicts. Solutions: use FlatList with nestedScrollEnabled (Android), SectionList for sections, or move external scrolling to FlatList via ListHeaderComponent.

How to animate FlatList element appearance?

Use the Animated API inside renderItem with a delay based on index. For scrolling, use onViewableItemsChanged to trigger animations. Libraries like react-native-reanimated and react-native-lottie simplify creating complex appearance animations.

What is VirtualizedList and how is it related to FlatList?

VirtualizedList is the base virtualization component on which FlatList and SectionList are built. FlatList is a wrapper around VirtualizedList with a simplified API for flat lists. VirtualizedList provides lower-level control but is rarely used directly.

Summary

  • FlatList is the main React Native component for high-performance lists with automatic virtualization and cell reuse
  • Virtualization renders only visible elements via windowSize and initialNumToRender, saving memory on large data sets
  • Required props: data, renderItem, and keyExtractor — ensure correct list operation
  • getItemLayout speeds up scrolling for fixed-height elements by eliminating dynamic measurement
  • Horizontal lists and carousels are configured via horizontal and snapToInterval for step-by-step scrolling
  • Pull-to-refresh and onEndReached implement infinite loading with protection against repeated calls
  • React.memo and useCallback are mandatory for renderItem — without them, every scroll triggers re-render of all elements

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also