Skip to main content
FlashList v2 brings significant improvements in performance, developer experience, and new features built specifically for React Native’s new architecture.

Requirements

FlashList v2 requires React Native’s new architecture. It will not work on the old architecture.

New Props

masonry

Enable masonry layout for grid-like interfaces with varying item heights. Previously available as MasonryFlashList, this is now a simple prop.
<FlashList
  data={data}
  masonry
  numColumns={3}
  renderItem={({ item }) => <MasonryItem item={item} />}
/>

onStartReached

Called when the scroll position gets within onStartReachedThreshold of the start of the content. Perfect for chat applications loading older messages.
<FlashList
  data={messageData}
  onStartReached={() => loadOlderMessages()}
  onStartReachedThreshold={0.1}
  renderItem={({ item }) => <MessageItem message={item} />}
/>

maintainVisibleContentPosition

Configuration for maintaining scroll position when content changes. This is enabled by default in v2 to reduce visible glitches.
  • disabled: Set to true to disable this feature (enabled by default)
  • autoscrollToTopThreshold: Automatically scroll to maintain position when content is added at the top
  • autoscrollToBottomThreshold: Automatically scroll to maintain position when content is added at the bottom
  • animateAutoScrollToBottom: Scroll with animation whenever autoscrollToBottom is triggered. Default is true
  • startRenderingFromBottom: If true, initial render will start from the bottom, useful for chat interfaces
<FlashList
  data={chatMessages}
  maintainVisibleContentPosition={{
    autoscrollToBottomThreshold: 0.2,
    startRenderingFromBottom: true,
  }}
  renderItem={({ item }) => <ChatMessage message={item} />}
/>

style

Style for the FlashList’s parent container.
We highly recommend not adding padding which can impact the size of the ScrollView inside. In most cases, contentContainerStyle should be enough.

maxItemsInRecyclePool

Maximum number of items in the recycle pool. These are cached items when they are scrolled off screen.
<FlashList
  data={data}
  maxItemsInRecyclePool={20}
  renderItem={({ item }) => <Item item={item} />}
/>
Unless you have a huge number of item types, you shouldn’t need to set this. Setting this to 0 disables the recycle pool and items will unmount once scrolled off screen.

optimizeItemArrangement

When enabled with masonry layout, this will try to reduce differences in column height by modifying item order.

onCommitLayoutEffect

Called before layout is committed. Can be used to measure list and make changes before paint.
Doing setState inside the callback can lead to infinite loops. Make sure FlashList’s props are memoized.

stickyHeaderConfig

Advanced configuration for sticky headers with new options:
<FlashList
  data={sectionData}
  stickyHeaderIndices={[0, 10, 20]}
  stickyHeaderConfig={{
    useNativeDriver: true,
    offset: 50, // Headers stick 50px from top
    backdropComponent: <BlurView style={StyleSheet.absoluteFill} />,
    hideRelatedCell: true,
  }}
  renderItem={({ item }) => <ListItem item={item} />}
/>
  • useNativeDriver: Use native driver for animations (default: true)
  • offset: Offset from top where sticky headers should stick (default: 0)
  • backdropComponent: Component to render behind sticky headers (e.g., blur effect)
  • hideRelatedCell: Hide the cell when displayed as sticky header (default: false)

onChangeStickyIndex

Callback invoked when the currently displayed sticky header changes.
<FlashList
  data={sectionData}
  stickyHeaderIndices={[0, 10, 20]}
  onChangeStickyIndex={(current, previous) => {
    console.log(`Sticky header changed from ${previous} to ${current}`);
  }}
  renderItem={({ item }) => <ListItem item={item} />}
/>

Changed Props

overrideItemLayout

This used to allow a way to change the span of items and provide size estimates. In v2, span is supported, but we no longer read the size estimates.
<FlashList
  data={gridData}
  numColumns={2}
  overrideItemLayout={(layout, item) => {
    layout.span = item.span; // Set span - size estimates no longer used
  }}
  renderItem={({ item }) => <GridItem item={item} />}
/>

New Features

Masonry as a Prop

masonry is now a prop on FlashList. It’s also possible to use overrideItemLayout with masonry.

RTL Support

FlashList v2 adds full support for RTL (right-to-left) layouts.

maintainVisibleContentPosition

Now enabled by default, this feature reduces visible glitches as much as possible. Chat apps without inverted mode are now possible.
If you plan on adding a large number of rows on top of the list, you may want to increase the drawDistance on the list.

Major Improvements

No More Size Estimates Required

FlashList v2 doesn’t ask for any estimates, making it much easier to use. Simply remove:
  • estimatedItemSize
  • estimatedListSize
  • estimatedFirstItemOffset

Precise Scrolling

scrollToIndex and scrollToItem are much more precise in v2.

Better Orientation Changes

Scrolling upwards after orientation change doesn’t cause layout glitches. The same is true for scrolling to items and scrolling upwards.

Improved Sticky Headers

Sticky headers use an Animated implementation, so minor gaps between them while scrolling aren’t visible anymore.

Enhanced Horizontal Lists

Horizontal lists are much improved, and items can also resize within the lists. We no longer render an extra item to measure list height.

Grid Layout Height Matching

In grid layout, if side-by-side items have different heights, then the shorter item will match the height of the tallest item. This wasn’t possible in v1.

contentContainerStyle Fully Supported

The contentContainerStyle prop is now fully supported.

Enhanced Ref Methods

The ref of FlashList has many more useful methods like getVisibleIndices and getLayout.

New Hooks

useLayoutState

Similar to useState but communicates the change in state to FlashList. Useful if you want to resize a child component based on a local state.
import { useLayoutState } from "@shopify/flash-list";

const MyItem = ({ item }) => {
  const [isExpanded, setIsExpanded] = useLayoutState(false);
  const height = isExpanded ? 150 : 80;

  return (
    <Pressable onPress={() => setIsExpanded(!isExpanded)}>
      <View style={{ height, padding: 16 }}>
        <Text>{item.title}</Text>
      </View>
    </Pressable>
  );
};
Item layout changes will still be detected using onLayout callback in the absence of useLayoutState, which might not look as smooth on a case-by-case basis.

useRecyclingState

Similar to useState but accepts a dependency array. On change of deps, the state gets reset without an additional setState call.
import { useRecyclingState } from "@shopify/flash-list";

const GridItem = ({ item }) => {
  const [isExpanded, setIsExpanded] = useRecyclingState(
    false,
    [item.id],
    () => {
      // runs on reset. Can be used to reset scroll positions of nested horizontal lists
    }
  );
  const height = isExpanded ? 100 : 50;

  return (
    <Pressable onPress={() => setIsExpanded(!isExpanded)}>
      <View style={{ height, backgroundColor: item.color }}>
        <Text>{item.title}</Text>
      </View>
    </Pressable>
  );
};
It also has the functionality of useLayoutState built in.

useMappingHelper

Returns a function that helps create optimal mapping keys for items when using .map() in your render methods.
import { useMappingHelper } from "@shopify/flash-list";

const MyComponent = ({ items }) => {
  const { getMappingKey } = useMappingHelper();

  return (
    <FlashList
      data={items}
      renderItem={({ item }) => <ItemComponent item={item} />}
    />
  );
};

// When mapping over items inside components:
const NestedList = ({ items }) => {
  const { getMappingKey } = useMappingHelper();

  return (
    <View>
      {items.map((item, index) => (
        <Text key={getMappingKey(item.id, index)}>{item.title}</Text>
      ))}
    </View>
  );
};
Using this ensures optimized recycling and performance for FlashList.

useFlashListContext

Exposes helpers to easily access ref of FlashList. It also exposes ref of ScrollView. Ideal for use within child components or CellRendererComponent.

New Helper Components

LayoutCommitObserver

A component that observes when FlashList commits a layout. This is particularly useful when you have one or more FlashLists somewhere down the component tree and need to know when all of them have finished their layout commit. Read more in the Layout Commit Observer guide.

Deprecated Props

The following props have been deprecated and should be removed:

Size Estimation Props (No Longer Needed)

  • estimatedItemSize: No longer used
  • estimatedListSize: No longer used
  • estimatedFirstItemOffset: No longer used

Deprecated Features

  • inverted: Use maintainVisibleContentPosition instead
  • onBlankArea: No plans to add or continue supporting this prop
  • disableHorizontalListHeightMeasurement: No longer needed
  • disableAutoLayout: There’s no auto layout in v2
  • MasonryFlashList: Replaced by masonry prop
  • getColumnFlex: Not supported in FlashList v2 with masonry prop

Next Steps

Ready to migrate? Check out the v2 Migration Guide for step-by-step instructions.

Build docs developers (and LLMs) love