Skip to main content
FlashList is a high-performance alternative to React Native’s FlatList. It uses cell recycling to achieve smooth scrolling with large datasets.

Usage

import { FlashList } from "@shopify/flash-list";

function MyList() {
  return (
    <FlashList
      data={items}
      renderItem={({ item }) => <ItemView item={item} />}
    />
  );
}

Props

Required Props

data
ReadonlyArray<T> | null | undefined
required
Array of items to render in the list.
<FlashList data={[{id: 1, title: 'Item 1'}]} />
renderItem
ListRenderItem<T> | null | undefined
required
Takes an item from data and renders it into the list.The function receives:
  • item: The item from data being rendered
  • index: The index corresponding to this item in the data array
  • target: Render context - "Cell", "StickyHeader", or "Measurement"
  • extraData: Value passed to the extraData prop
<FlashList
  data={items}
  renderItem={({ item, index, target }) => (
    <Text>{item.title}</Text>
  )}
/>

Layout Props

horizontal
boolean
If true, renders items next to each other horizontally instead of stacked vertically.Default: false
numColumns
number
Multiple columns can only be rendered with horizontal={false} and will zig-zag like a flexWrap layout.Items should all be the same height - masonry layouts are not supported on old architecture.
<FlashList numColumns={3} />
drawDistance
number
Draw distance for advanced rendering in dp/px. Controls how far off-screen items are rendered.Larger values improve scroll performance but use more memory.

Component Props

CellRendererComponent
ComponentType<any>
Each cell is rendered using this element. Can be a React Component Class or render function.The root component should always be a CellContainer which is the default. The props include:
  • onLayout: Method for updating layout data
  • index: Index of the cell in the list
  • style: Cell positioning and sizing styles
Changing layout of the cell can conflict with native layout operations. You may need to set disableAutoLayout to true to prevent this.
ItemSeparatorComponent
ComponentType<any> | null
Rendered in between each item, but not at the top or bottom.By default, leadingItem and trailingItem props are provided.
<FlashList
  ItemSeparatorComponent={() => <View style={{ height: 1, backgroundColor: '#ccc' }} />}
/>
ListEmptyComponent
ComponentType<any> | ReactElement | null
Rendered when the list is empty. Can be a React Component (e.g. SomeComponent) or a React element (e.g. <SomeComponent />).
<FlashList
  ListEmptyComponent={<Text>No items found</Text>}
/>
ListHeaderComponent
ComponentType<any> | ReactElement | null
Rendered at the top of all the items. Can be a React Component or a React element.
<FlashList
  ListHeaderComponent={<Text>Header</Text>}
/>
ListHeaderComponentStyle
StyleProp<ViewStyle>
Styling for internal View for ListHeaderComponent.
Rendered at the bottom of all the items. Can be a React Component or a React element.
<FlashList
  ListFooterComponent={<ActivityIndicator />}
/>
Styling for internal View for ListFooterComponent.
renderScrollComponent
ComponentType<ScrollViewProps>
Rendered as the main scroll view. Use this to customize the underlying scroll component.
<FlashList
  renderScrollComponent={(props) => <CustomScrollView {...props} />}
/>

Data Management Props

keyExtractor
(item: T, index: number) => string
Used to extract a unique key for a given item at the specified index.Key is used for optimizing performance. Defining keyExtractor is also necessary when doing layout animations to uniquely identify animated components.
<FlashList
  keyExtractor={(item) => item.id.toString()}
/>
extraData
any
A marker property for telling the list to re-render (since it implements PureComponent).If any of your renderItem, Header, Footer, etc. functions depend on anything outside of the data prop, stick it here and treat it immutably.
<FlashList extraData={selectedId} />
getItemType
(item: T, index: number, extraData?: any) => string | number | undefined
Allows developers to override type of items. This will improve recycling if you have different types of items in the list.Right type will be used for the right item. Default type is 0.
Performance: This method is called very frequently. Keep it fast.
<FlashList
  getItemType={(item) => item.type}
/>
overrideItemLayout
(layout: { span?: number }, item: T, index: number, maxColumns: number, extraData?: any) => void
This method can be used to change column span of an item.Changing item span is useful when you have grid layouts (numColumns > 1) and you want few items to be bigger than the rest.Modify the given layout. Do not return. FlashList will fallback to default values if this is ignored.
Performance: This method is called very frequently. Keep it fast.
<FlashList
  numColumns={3}
  overrideItemLayout={(layout, item) => {
    if (item.featured) {
      layout.span = 3; // Full width
    }
  }}
/>

Scroll & Interaction Props

initialScrollIndex
number
Instead of starting at the top with the first item, start at initialScrollIndex.
<FlashList initialScrollIndex={10} />
initialScrollIndexParams
{ viewOffset?: number }
Additional configuration for initialScrollIndex.Use viewOffset to apply an offset to the initial scroll position as defined by initialScrollIndex. Ignored if initialScrollIndex is not set.
<FlashList
  initialScrollIndex={5}
  initialScrollIndexParams={{ viewOffset: 100 }}
/>
onEndReached
() => void
Called once when the scroll position gets within onEndReachedThreshold of the rendered content.
<FlashList
  onEndReached={() => loadMoreItems()}
  onEndReachedThreshold={0.5}
/>
onEndReachedThreshold
number
How far from the end (in units of visible length of the list) the bottom edge of the list must be from the end of the content to trigger the onEndReached callback.Thus a value of 0.5 will trigger onEndReached when the end of the content is within half the visible length of the list.Default: 0.5
onStartReached
() => void
Called once when the scroll position gets within onStartReachedThreshold of the start of the content.
<FlashList
  onStartReached={() => loadPreviousItems()}
  onStartReachedThreshold={0.2}
/>
onStartReachedThreshold
number
How far from the start (in units of visible length of the list) the top edge of the list must be from the start of the content to trigger the onStartReached callback.Thus a value of 0.5 will trigger onStartReached when the start of the content is within half the visible length of the list.Default: 0.2
onLoad
(info: { elapsedTimeInMs: number }) => void
This event is raised once the list has drawn items on the screen. It also reports elapsedTimeInMs which is the time it took to draw the items.This is required because FlashList doesn’t render items in the first cycle. Items are drawn after it measures itself at the end of first render.If you’re using ListEmptyComponent, this event is raised as soon as ListEmptyComponent is rendered.
<FlashList
  onLoad={({ elapsedTimeInMs }) => {
    console.log(`List loaded in ${elapsedTimeInMs}ms`);
  }}
/>
onRefresh
() => void
If provided, a standard RefreshControl will be added for “Pull to Refresh” functionality.Make sure to also set the refreshing prop correctly.
<FlashList
  onRefresh={handleRefresh}
  refreshing={isRefreshing}
/>
refreshing
boolean
Set this true while waiting for new data from a refresh.
progressViewOffset
number
Set this when offset is needed for the loading indicator to show correctly.

Viewability Props

onViewableItemsChanged
(info: { viewableItems: ViewToken<T>[], changed: ViewToken<T>[] }) => void
Called when the viewability of rows changes, as defined by the viewabilityConfig prop.Array of changed includes ViewTokens for both visible and non-visible items. You can use the isViewable flag to filter the items.If you are tracking the time a view becomes (non-)visible, use the timestamp property.
<FlashList
  onViewableItemsChanged={({ viewableItems, changed }) => {
    viewableItems.forEach(token => {
      if (token.isViewable) {
        console.log('Item is visible:', token.item);
      }
    });
  }}
  viewabilityConfig={{
    itemVisiblePercentThreshold: 50
  }}
/>
viewabilityConfig
ViewabilityConfig
A default configuration for determining whether items are viewable.
Changing viewabilityConfig on the fly is not supported.
viewabilityConfigCallbackPairs
ViewabilityConfigCallbackPair<T>[]
List of ViewabilityConfig/onViewableItemsChanged pairs.A specific onViewableItemsChanged will be called when its corresponding ViewabilityConfig’s conditions are met.
<FlashList
  viewabilityConfigCallbackPairs={[
    {
      viewabilityConfig: { itemVisiblePercentThreshold: 50 },
      onViewableItemsChanged: handleHalfVisible
    },
    {
      viewabilityConfig: { itemVisiblePercentThreshold: 100 },
      onViewableItemsChanged: handleFullyVisible
    }
  ]}
/>

Sticky Header Props

stickyHeaderIndices
number[]
Array of indices of items that should stick to the top of the list as you scroll.Inherited from React Native’s ScrollView.
<FlashList stickyHeaderIndices={[0, 5, 10]} />
onChangeStickyIndex
(current: number, previous: number) => void
Callback invoked when the currently displayed sticky header changes.Receives the current sticky header index and the previous sticky header index. This is useful for tracking which header is currently stuck at the top while scrolling.The index refers to the position of the item in your data array that’s being used as a sticky header.
<FlashList
  stickyHeaderIndices={[0, 5, 10]}
  onChangeStickyIndex={(current, previous) => {
    console.log(`Sticky header changed from ${previous} to ${current}`);
  }}
/>
stickyHeaderConfig
object
Configuration for sticky header behavior.
<FlashList
  stickyHeaderIndices={[0]}
  stickyHeaderConfig={{
    offset: 60,
    backdropComponent: <BlurView />
  }}
/>

Advanced Props

overrideProps
OverrideProps
Allows overriding internal ScrollView props. Props provided here are spread onto the internal ScrollView after all other props, so they take highest priority.This can be useful for cases where you need to set a style on the ScrollView itself rather than the outer container. For example, to enable visible overflow:
<FlashList
  style={{ overflow: "visible" }}
  overrideProps={{ style: { overflow: "visible" } }}
/>
Use with caution — overriding internal props may interfere with FlashList’s layout and recycling behavior.
maxItemsInRecyclePool
number
Maximum number of items in the recycle pool. These are the items that are cached in the recycle pool when they are scrolled off the screen.Unless you have a huge number of item types, you shouldn’t need to set this. Setting this to 0 will disable the recycle pool and items will unmount once they are scrolled off the screen.There’s no limit by default.
masonry
boolean
Enable masonry layout. Items can have different heights and will be arranged in a Pinterest-style layout.
<FlashList masonry numColumns={2} />
optimizeItemArrangement
boolean
If enabled, MasonryFlashList will try to reduce difference in column height by modifying item order.
maintainVisibleContentPosition
object
Configuration for maintaining scroll position when content changes. Useful for chat-like interfaces where new messages can be added at the top or bottom.
<FlashList
  maintainVisibleContentPosition={{
    autoscrollToBottomThreshold: 100,
    startRenderingFromBottom: true
  }}
/>
onCommitLayoutEffect
() => void
Called when the layout is committed. Can be used to measure list.
Doing set state inside the callback can lead to infinite loops. Make sure FlashList’s props are memoized.
style
StyleProp<ViewStyle>
Style for the RecyclerView’s parent container.Please avoid anything which can mess size of children in this view. For example, margin is okay but padding is not.
To enable overflow: "visible", you must also set it on the internal ScrollView via overrideProps.

ScrollView Props

FlashList also accepts all ScrollView props except maintainVisibleContentPosition (use the FlashList-specific version instead on new architecture). Common ScrollView props include:
  • contentContainerStyle
  • showsVerticalScrollIndicator
  • showsHorizontalScrollIndicator
  • onScroll
  • scrollEventThrottle
  • inverted
  • And many more from React Native’s ScrollView

Ref Methods

Access these methods by passing a ref to FlashList:
const listRef = useRef<FlashListRef<ItemType>>(null);

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

// Later:
listRef.current?.scrollToIndex({ index: 5, animated: true });

Scrolling Methods

scrollToOffset
(params: ScrollToOffsetParams) => void
Scrolls the list to a specific offset position.Use this method when you want precise control over the scroll position in pixels rather than by item index.
listRef.current?.scrollToOffset({ offset: 200, animated: true });
scrollToIndex
(params: ScrollToIndexParams) => Promise<void>
Scrolls to a specific index in the list. This is the most common method to scroll to a particular item.
listRef.current?.scrollToIndex({
  index: 4,
  animated: true,
  viewPosition: 0.5 // Center the item
});
scrollToItem
(params: ScrollToItemParams<T>) => void
Scrolls to a specific item in the list.Similar to scrollToIndex, but works with the item reference instead of its index. Useful when you have a reference to an item but don’t know its index.
const targetItem = data[10];
listRef.current?.scrollToItem({
  item: targetItem,
  animated: true
});
scrollToEnd
(params?: ScrollToEdgeParams) => void
Scrolls to the end of the list.
listRef.current?.scrollToEnd({ animated: true });
scrollToTop
(params?: ScrollToEdgeParams) => void
Scrolls to the top (or start) of the list.
listRef.current?.scrollToTop({ animated: true });
flashScrollIndicators
() => void
Makes the scroll indicators flash momentarily.Useful to indicate to users that there is more content to scroll.
listRef.current?.flashScrollIndicators();

Information Methods

getLayout
(index: number) => RVLayout | undefined
Returns the layout information for a specific item.Use this to get position and size information for an item at a given index.
const itemLayout = listRef.current?.getLayout(5);
console.log(`Item 5 position: (${itemLayout.x}, ${itemLayout.y})`);
computeVisibleIndices
() => { startIndex: number; endIndex: number }
Returns the currently visible item indices.Use this to determine which items are currently visible to the user.
const { startIndex, endIndex } = listRef.current?.computeVisibleIndices();
console.log(`Visible items: ${startIndex} to ${endIndex}`);
getFirstVisibleIndex
() => number
Returns the index of the first visible item.Convenience method when you only need the first visible item.
const firstVisibleIndex = listRef.current?.getFirstVisibleIndex();
getFirstItemOffset
() => number
Returns the offset of the first item (accounts for header/padding).Useful when implementing custom scroll behavior or calculating positions.
const offset = listRef.current?.getFirstItemOffset();
getWindowSize
() => { width: number; height: number }
Returns the current viewport dimensions.
const { width, height } = listRef.current?.getWindowSize();
getChildContainerDimensions
() => { width: number; height: number }
Returns the dimensions of the child container.
getAbsoluteLastScrollOffset
() => number
Returns the absolute last scroll offset.Useful for implementing custom scroll tracking functionality.
props
RecyclerViewProps<T>
Get access to current props.

Native Access Methods

getNativeScrollRef
() => CompatScroller | null
Returns the underlying native scroll view reference.Use this when you need direct access to the native scroll component. This is generally not recommended for regular use.
getScrollResponder
() => any
Returns a reference to the scroll responder.Useful for more advanced scroll handling and integrations.
getScrollableNode
() => any
Returns the underlying scrollable node.Primarily used for platform-specific integrations.

Advanced Methods

recomputeViewableItems
() => void
Forces recalculation of viewable items (viewability callbacks).Call this after any operation that might affect item visibility but doesn’t trigger a scroll event.
listRef.current?.recomputeViewableItems();
recordInteraction
() => void
Marks the list as having been interacted with.Call this method when you want to manually trigger the onViewableItemsChanged callback without an actual scroll event.
prepareForLayoutAnimationRender
() => void
Disables item recycling in preparation for layout animations.Call this before performing layout animations to prevent visual glitches. Remember to reset disableRecycling after animations complete.
listRef.current?.prepareForLayoutAnimationRender();
clearLayoutCacheOnUpdate
() => void
Clears the layout cache on update.Call this when you want to clear the layout cache on update. Can be useful for carousels when orientation changes.This should be called before the render and not in an effect.
listRef.current?.clearLayoutCacheOnUpdate();

Type Definitions

ListRenderItemInfo

interface ListRenderItemInfo<TItem> {
  item: TItem;
  index: number;
  target: RenderTarget;
  extraData?: any;
}

RenderTarget

type RenderTarget = "Cell" | "StickyHeader" | "Measurement";
FlashList may render your items for multiple reasons:
  • Cell: This is for your list item
  • Measurement: Might be invoked for size measurement and won’t be visible. You can ignore this in analytics.
  • StickyHeader: This is for your sticky header. Use this to change your item’s appearance while it’s being used as a sticky header.

ViewToken

interface ViewToken<T> {
  item: T;
  key: string;
  index: number | null;
  isViewable: boolean;
  timestamp: number;
}

Build docs developers (and LLMs) love