JSPM

  • Created
  • Published
  • Downloads 466913
  • Score
    100M100P100Q183321F
  • License MIT

FlashList is a more performant FlatList replacement

Package Exports

  • @shopify/flash-list
  • @shopify/flash-list/dist/FlashListProps
  • @shopify/flash-list/dist/FlashListProps.js
  • @shopify/flash-list/dist/GridLayoutProviderWithProps
  • @shopify/flash-list/dist/GridLayoutProviderWithProps.js
  • @shopify/flash-list/dist/PureComponentWrapper
  • @shopify/flash-list/dist/PureComponentWrapper.js
  • @shopify/flash-list/dist/errors/CustomError
  • @shopify/flash-list/dist/errors/CustomError.js
  • @shopify/flash-list/dist/errors/ExceptionList
  • @shopify/flash-list/dist/errors/ExceptionList.js
  • @shopify/flash-list/dist/errors/Warnings
  • @shopify/flash-list/dist/errors/Warnings.js
  • @shopify/flash-list/dist/index.js
  • @shopify/flash-list/dist/native/auto-layout/AutoLayoutView
  • @shopify/flash-list/dist/native/auto-layout/AutoLayoutView.js
  • @shopify/flash-list/dist/native/cell-container/CellContainer
  • @shopify/flash-list/dist/native/cell-container/CellContainer.js
  • @shopify/flash-list/dist/native/config/PlatformHelper
  • @shopify/flash-list/dist/native/config/PlatformHelper.js
  • @shopify/flash-list/dist/utils/ContentContainerUtils
  • @shopify/flash-list/dist/utils/ContentContainerUtils.js
  • @shopify/flash-list/dist/viewability/ViewabilityManager
  • @shopify/flash-list/dist/viewability/ViewabilityManager.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@shopify/flash-list) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

FlashList Image

FlashList v2

FlashList v2 has been rebuilt from the ground up for RN's new architecture and delivers fast performance, higher precision, and better ease of use compared to v1. We've achieved all this while moving to a JS-only solution! One of the key advantages of FlashList v2 is that it doesn't require any estimates. It also introduces several new features compared to v1.

⚠️ IMPORTANT: FlashList v2.x has been designed to fully leverage the new architecture. Old architecture will only be supported while FlashList v2 is in alpha/beta and will be dropped once it's ready. When run on old architecture, we just fall back to v1.x which doesn't have any of the new features.

⚠️ IMPORTANT: FlashList v2.x is in alpha and may have some issues. Please report any issues or edge cases you run into. We're actively working on testing and optimizing v2 so some things might change in the final version. We also highly recommend using it with RN 0.78+ for optimal performance.

Old architecture / FlashList v1

If you're running on old architecture or using FlashList v1.x, you can access the documentation specific to v1 here: FlashList v1 Documentation.

Web support

FlashList v2 has web support. Most of the features should work but we're not actively testing it right now. If you run into an issue, please raise it on GitHub.

Installation

Add the package to your project via yarn add @shopify/flash-list@alpha and run pod install in the ios directory.

Usage

But if you are familiar with FlatList, you already know how to use FlashList. You can try out FlashList by changing the component name or refer to the example below:

import React from "react";
import { View, Text } from "react-native";
import { FlashList } from "@shopify/flash-list";

const DATA = [
  {
    title: "First Item",
  },
  {
    title: "Second Item",
  },
];

const MyList = () => {
  return (
    <FlashList
      data={DATA}
      renderItem={({ item }) => <Text>{item.title}</Text>}
    />
  );
};

New props

  • masonry: Enable masonry layout for grid-like interfaces with varying item heights.

    <FlashList
      data={data}
      masonry
      numColumns={3}
      renderItem={({ item }) => <MasonryItem item={item} />}
    />
  • optimizeItemArrangement: When enabled, masonry layout will try to reduce differences in column height by modifying item order.

  • onStartReached: Called when the scroll position gets within onStartReachedThreshold of the start of the content.

    <FlashList
      data={messageData}
      onStartReached={() => loadOlderMessages()}
      onStartReachedThreshold={0.1}
      renderItem={({ item }) => <MessageItem message={item} />}
    />
  • onStartReachedThreshold: How far from the start the top edge of the list must be to trigger onStartReached.

  • maxItemsInRecyclePool: Maximum number of items in the recycle pool (Not required unless the number of item types is huge).

  • style: Style for the FlashList's parent container. We highly recommend not adding padding which can impact the size of the ScrollView inside. We operate on the assumption that the size of parent view and ScrollView is the same. In most cases, contentContainerStyle should be enough so avoid using this.

  • maintainVisibleContentPosition: Configuration for maintaining scroll position when content changes:

    • 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.
    • 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} />}
    />
  • 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.

Deprecated (will be removed after alpha/beta)

  • estimatedItemSize: No longer used.
  • estimatedListSize: No longer used.
  • estimatedFirstItemOffset: No longer used.
  • inverted: We have added maintainVisibleContentPosition support, so we don't want to maintain inverted mode.
  • onBlankArea: We don't have plans to add or continue supporting this prop.
  • disableHorizontalListHeightMeasurement: No longer needed.
  • disableAutoLayout: There's no auto layout in v2.
  • MasonryFlashList will be replaced by masonry prop.
  • getColumnFlex from MasonryFlashList will not be supported in FlashList v2 with masonry prop.

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
      }}
      renderItem={({ item }) => <GridItem item={item} />}
    />

New features

  • masonry is now a prop on FlashList. It's now also possible to use overrideItemLayout with masonry.
  • maintainVisibleContentPosition is available and now enabled by default. We use this to reduce visible glitches as much as possible. Chat apps without inverted will also be possible. Please note that if you plan on adding a large number of rows on top of the list, then you may want to increase the drawDistance on the list.
  • onStartReached callback is now available with a configurable threshold.
  • We've also added support for RTL layouts.

Improvements

  • scrollToIndex and scrollToItem are much more precise.
  • Scrolling upwards after orientation change doesn't cause layout glitches. The same is true for scrolling to items and scrolling upwards.
  • stickyHeaders use an Animated implementation, so minor gaps between them while scrolling aren't visible anymore.
  • FlashList does not ask for any estimates, which makes it much easier to use.
  • Horizontal Lists are much improved, and items can also resize within the lists. We no longer render an extra item to measure list height.
  • 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.
  • The ref of FlashList has many more useful methods like getVisibleIndices and getLayout.
  • contentContainerStyle prop is fully supported now.

Things to know

  • keyExtractor is important to prevent glitches due to item layout changes when going upwards. We highly recommend having a valid keyExtractor with v2.

  • Avoid adding keys directly to components which can break recycling. Same as v1. More info here.

  • useLayoutState: This is similar to useState but communicates the change in state to FlashList. It's useful if you want to resize a child component based on a local state. 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.

    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>
      );
    };
  • useRecyclingState: Similar to useState but accepts a dependency array. On change of deps, the state gets reset without an additional setState call. Useful for maintaining local item state if really necessary. It also has the functionality of useLayoutState built in.

    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>
      );
    };
  • useMappingHelper: Returns a function that helps create optimal mapping keys for items when using .map() in your render methods. Using this ensures optimized recycling and performance for FlashList.

    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(index, item.id)}>{item.title}</Text>
          ))}
        </View>
      );
    };
  • If you're nesting horizontal FlashLists in vertical lists, we highly recommend the vertical list to be FlashList too. We have optimizations to wait for child layout to complete which can improve load times.

  • For chat apps, consider increasing drawDistance to 500 or higher if you're going to add a lot of items to the top. Higher drawDistance can remove some flickers. 500-1000 for chat can be okay. We would like to hear from you if you run into issues.

  • Memoizing props passed to FlashList is more important in v2. v1 was more selective about updating items, but this was often perceived as a bug by developers. We will not follow that approach and will instead allow developers to ensure that props are memoized. We will stop re-renders of children wherever it is obvious.

App / Playground

The fixture is an example app showing how to use the library.