Skip to main content
If you’re familiar with FlatList, you already know how to use FlashList. You can try out FlashList by simply changing the component name.

Quick Start

1

Install FlashList

npm install @shopify/flash-list
2

Change the import

- import { FlatList } from 'react-native';
+ import { FlashList } from '@shopify/flash-list';
3

Update the component

- <FlatList
+ <FlashList
    data={data}
    renderItem={renderItem}
    keyExtractor={item => item.id}
  />
That’s it! In most cases, FlashList is a drop-in replacement for FlatList.

Basic Example

import React from 'react';
import { FlatList, Text, View } from 'react-native';

const DATA = [
  { id: '1', title: 'First Item' },
  { id: '2', title: 'Second Item' },
  { id: '3', title: 'Third Item' },
];

const MyList = () => {
  return (
    <FlatList
      data={DATA}
      renderItem={({ item }) => (
        <View style={{ padding: 20 }}>
          <Text>{item.title}</Text>
        </View>
      )}
      keyExtractor={item => item.id}
    />
  );
};

Important Differences

While FlashList is largely compatible with FlatList, there are some important differences to be aware of:

Required: estimatedItemSize (v1 only)

If you’re using FlashList v2, you can skip this section. Size estimates are not required in v2.
In FlashList v1, you may need to provide an estimatedItemSize for optimal performance:
<FlashList
  data={data}
  renderItem={renderItem}
  estimatedItemSize={50}
/>

Remove Explicit key Props

Remove explicit key prop definitions from your renderItem hierarchy. FlashList handles keys internally.
Before - FlatList
renderItem={({ item }) => (
  <View key={item.id}> {/* Remove this key */}
    <Text>{item.title}</Text>
  </View>
)}
After - FlashList
renderItem={({ item }) => (
  <View> {/* No key needed here */}
    <Text>{item.title}</Text>
  </View>
)}
Instead, always use keyExtractor:
<FlashList
  data={data}
  renderItem={renderItem}
  keyExtractor={item => item.id} // Define keys here
/>

Using .map() Inside Items

If you’re using .map() inside your rendered items, use the useMappingHelper hook:
Before - FlatList
const MyItem = ({ item }) => (
  <View>
    {item.tags.map((tag, index) => (
      <Text key={tag}>{tag}</Text>
    ))}
  </View>
);
After - FlashList
import { useMappingHelper } from '@shopify/flash-list';

const MyItem = ({ item }) => {
  const { getMappingKey } = useMappingHelper();

  return (
    <View>
      {item.tags.map((tag, index) => (
        <Text key={getMappingKey(tag, index)}>{tag}</Text>
      ))}
    </View>
  );
};
This ensures optimal performance with FlashList’s recycling system.

Prop Differences

Supported Props

FlashList supports most FlatList props including:

Core Props

  • data
  • renderItem
  • keyExtractor
  • extraData

Layout Props

  • horizontal
  • numColumns
  • contentContainerStyle
  • ListHeaderComponent

Callbacks

  • onEndReached
  • onEndReachedThreshold
  • onViewableItemsChanged
  • onRefresh

Components

  • ListFooterComponent
  • ListEmptyComponent
  • ItemSeparatorComponent

Unsupported FlatList Props

The following FlatList props are not supported in FlashList:
Performance-related props (not needed due to FlashList’s architecture):
  • getItemLayout - FlashList automatically calculates layouts
  • initialNumToRender - FlashList manages rendering differently
  • maxToRenderPerBatch - Not applicable to FlashList’s rendering model
  • windowSize - FlashList uses a different windowing strategy
  • updateCellsBatchingPeriod - Not needed in FlashList
  • disableVirtualization - Goes against FlashList’s core design
Other unsupported props:
  • columnWrapperStyle - Not currently implemented
  • debug - Use FlashList’s built-in performance tracking instead
  • listKey - Not required in FlashList
  • onScrollToIndexFailed - Not currently implemented
  • setNativeProps - Not available in FlashList
We don’t currently plan to implement these props as they don’t align with FlashList’s architecture or provide value in its context.

Additional Features in FlashList

FlashList includes several features not available in FlatList:

New Props

Draw distance for advanced rendering control:
<FlashList
  data={data}
  renderItem={renderItem}
  drawDistance={500} // in dp/px
/>
Improve recycling performance for heterogeneous lists:
<FlashList
  data={mixedData}
  renderItem={renderItem}
  getItemType={(item) => {
    return item.type; // 'header', 'image', 'text', etc.
  }}
/>
Customize item spans for grid layouts:
<FlashList
  data={gridData}
  numColumns={2}
  overrideItemLayout={(layout, item) => {
    layout.span = item.isWide ? 2 : 1; // Full width or half
  }}
  renderItem={renderItem}
/>
Called once when the list has drawn items:
<FlashList
  data={data}
  renderItem={renderItem}
  onLoad={({ elapsedTimeInMs }) => {
    console.log(`List loaded in ${elapsedTimeInMs}ms`);
  }}
/>

New Methods

FlashList provides extra methods through its ref:
const listRef = useRef(null);

// Get visible indices
const visibleIndices = listRef.current?.getVisibleIndices();

// Get list layout
const layout = listRef.current?.getLayout();

// Get first visible index
const firstVisible = listRef.current?.getFirstVisibleIndex();

// Flash scroll indicators
listRef.current?.flashScrollIndicators();

<FlashList
  ref={listRef}
  data={data}
  renderItem={renderItem}
/>

Migration Steps

Follow these steps when migrating from FlatList to FlashList:
1

Install and change imports

Install FlashList and update your imports as shown above.
2

Remove explicit key props

Scan your renderItem hierarchy for explicit key prop definitions and remove them. Use keyExtractor instead.
3

Add useMappingHelper for .map()

If you use .map() inside rendered items, implement the useMappingHelper hook.
4

Check useState usage

Review components in your renderItem hierarchy that use useState. Due to FlashList’s recycling, you may need to use useRecyclingState instead.
FlashList recycles view components as you scroll. If a component maintains local state with useState, that state might not reset when the component is recycled for a different item.
Before - Potential issue
const MyItem = ({ item }) => {
  const [expanded, setExpanded] = useState(false);
  // This state persists across recycling!

  return (
    <View>
      <Text>{item.title}</Text>
      {expanded && <Text>{item.details}</Text>}
    </View>
  );
};
After - Fixed with useRecyclingState
import { useRecyclingState } from '@shopify/flash-list';

const MyItem = ({ item }) => {
  const [expanded, setExpanded] = useRecyclingState(
    false,
    [item.id] // State resets when item.id changes
  );

  return (
    <View>
      <Text>{item.title}</Text>
      {expanded && <Text>{item.details}</Text>}
    </View>
  );
};
5

Use getItemType for heterogeneous lists

If your list has different types of items (headers, images, text, etc.), pass their types using getItemType to improve performance.
<FlashList
  data={data}
  getItemType={(item) => item.type}
  renderItem={({ item }) => {
    switch (item.type) {
      case 'header':
        return <HeaderItem item={item} />;
      case 'image':
        return <ImageItem item={item} />;
      default:
        return <TextItem item={item} />;
    }
  }}
/>
6

Test in release mode

Always test performance in release mode, not dev mode. FlashList can appear slower in dev mode.
# iOS
npx react-native run-ios --configuration Release

# Android
npx react-native run-android --variant=release
7

Memoize props

Memoize props passed to FlashList for optimal performance:
const memoizedData = useMemo(() => data, [data]);
const memoizedRenderItem = useCallback(
  ({ item }) => <Item item={item} />,
  []
);

<FlashList
  data={memoizedData}
  renderItem={memoizedRenderItem}
/>
8

Add keyExtractor (highly recommended)

While not strictly required, keyExtractor is highly recommended to prevent layout glitches:
<FlashList
  data={data}
  keyExtractor={(item) => item.id}
  renderItem={renderItem}
/>

Common Patterns

Pull to Refresh

<FlatList
  data={data}
  renderItem={renderItem}
  refreshing={refreshing}
  onRefresh={onRefresh}
/>

Infinite Scroll

<FlatList
  data={data}
  renderItem={renderItem}
  onEndReached={loadMore}
  onEndReachedThreshold={0.5}
/>

Grid Layout

<FlatList
  data={data}
  renderItem={renderItem}
  numColumns={2}
/>

Horizontal List

<FlatList
  data={data}
  renderItem={renderItem}
  horizontal
/>

Performance Comparison

FlashList significantly outperforms FlatList, especially for:
  • Long lists (100+ items)
  • Lists with complex items
  • Frequent data updates
  • Heterogeneous content
Typical performance improvements:
  • 5-10x faster initial render
  • Significantly reduced blank cells during fast scrolling
  • Lower memory usage
  • Smoother animations and interactions

Troubleshooting

Possible causes:
  1. Testing in dev mode (test in release mode)
  2. Items have varying heights but no getItemType specified
  3. Heavy computation in renderItem (memoize components)
  4. Low drawDistance value (increase if needed)
Solutions:
// Add getItemType for varying heights
<FlashList
  getItemType={(item) => item.type}
  // ...
/>

// Increase draw distance if needed
<FlashList
  drawDistance={500}
  // ...
/>

// Memoize rendered items
const MemoizedItem = memo(({ item }) => <Item item={item} />);
Possible causes:
  1. Missing keyExtractor
  2. State not resetting due to recycling
  3. Props not memoized properly
Solutions:
// Add keyExtractor
<FlashList
  keyExtractor={(item) => item.id}
  // ...
/>

// Use useRecyclingState for local state
import { useRecyclingState } from '@shopify/flash-list';

const MyItem = ({ item }) => {
  const [state, setState] = useRecyclingState(initialState, [item.id]);
  // ...
};

// Memoize props
const memoizedData = useMemo(() => data, [data]);
const memoizedRenderItem = useCallback(renderItem, []);
Possible causes:
  1. Inconsistent item heights without proper getItemType
  2. Custom CellRendererComponent interfering with layout
  3. Padding/margin issues in contentContainerStyle
Solutions:
// Use getItemType for consistent types
<FlashList
  getItemType={(item) => item.type}
  // ...
/>

// Check contentContainerStyle
<FlashList
  contentContainerStyle={{
    paddingHorizontal: 16, // Safe
    paddingVertical: 16,   // Safe
    // Avoid complex styling here
  }}
  // ...
/>

Next Steps

Usage Guide

Learn about all FlashList props and methods

Performant Components

Optimize your list items for maximum performance

Recycling

Understand how FlashList recycles components

What's New in v2

Explore FlashList v2 features (if using new architecture)

Build docs developers (and LLMs) love