W↓
All docs
🔑
Sign Up/Sign In
legendapp.com/open-source/list/
Public Link
Apr 8, 2025, 12:27:30 PM - complete - 38.8 kB
Starting URLs:
https://legendapp.com/open-source/list/api/gettingstarted/
Crawl Prefixes:
https://legendapp.com/open-source/list/
## Page: https://legendapp.com/open-source/list/api/gettingstarted/ Legend List is a high performance virtualized ScrollView library for React Native. Compared to FlatList and FlashList it’s faster, simpler, and has useful features they don’t support. * ✨ Extremely fast * ✨ Dynamic item sizes * ✨ Optional recycling * ✨ Bidirectional infinite lists * ✨ Chat list without inverting * ✨ Maintain content view position * ✨ Recycling hooks For more information, listen to Jay’s conversation on React Native Radio here. ## Install ## Usage Legend List is a virtualized ScrollView component for React Native with optional recycling, that can massively increase performance of rendering long lists. Rather than rendering every item in the list, it only renders the items that are in view, which significantly reduces the amount of items that need to render. Legend List is a drop-in replacement for FlatList or FlashList. So since you’re likely coming from one of those, we’ll start with a guide on how to switch. ### Switch from FlashList If you’re coming from FlashList, in most cases you can just rename the component and it will work as expected. But note that Legend List does not recycle items by default, so to match FlashList’s behavior you can enable `recycleItems`. return ( <FlashList <LegendList data={items} renderItem={({ item }) => <Text>{item.title}</Text>} estimatedItemSize={320} recycleItems />) ### Switch from FlatList If you’re coming from FlatList, you’ll just want to add at least one prop, the `estimatedItemSize`. Legend List automatically lays out your items in a very high performance way, and a hint for what size the items are likely to be will help it be as fast as possible. return ( <FlatList <LegendList data={items} renderItem={({ item }) => <Text>{item.title}</Text>} estimatedItemSize={320} />) If you first render a LegendList without an `estimatedItemSize` it will suggest an optimal item size based on the rendered items, so that can help you find the right number. See Props for all properties of LegendList. ## Beta Legend List is in beta. It seems to be feature complete and reliable, but we are just taking some time to take feedback from the community and make sure it’s stable for a 1.0 release. This documentation is still early. ## Supported Platforms * Android * IOS * MacOS Join us on Discord or Github to get involved with the Legend community. Talk to Jay on Bluesky or Twitter. ## Contributing We welcome contributions! Please read our Contributing Guide on Github. And we welcome documentation PRs in our documentation repo. ## Legend Kit Legend Kit is our early but growing collection of high performance headless components, general purpose observables, transformer computeds, React hooks that don’t re-render, and observable tools for popular frameworks. Check out Legend Kit to learn more. --- ## Page: https://legendapp.com/open-source/list/api/props/ Below is a list of all the properties for LegendList: ## Required Props * * * ### data data: ItemT[]; An array of the items to render. This can also be an array of keys if you want to get the item by key in renderItem. ### estimatedItemSize estimatedItemSize?: number; An estimated size for all items which is used to estimate the list layout before items actually render. If you don’t provide this, it will log a suggested value for optimal performance. ### renderItem renderItem?: (props: LegendListRenderItemProps<ItemT>) => ReactNode; Takes an item from data and renders it into the list. See React Native Docs. ## Recommended Props * * * keyExtractor?: (item: ItemT, index: number) => string; Highly recommended. The `keyExtractor` prop lets Legend List save item layouts by key, so that if the `data` array changes it can reuse previous layout information and only update the changed items. See Use key extractor. If LegendList detects duplicate keys, it will log a warning. ## Optional Props * * * ### alignItemsAtEnd alignItemsAtEnd?: boolean; // default: false Aligns to the end of the screen, so if there’s only a few items there will be enough padding at the top to make them appear to be at the bottom. See Chat interfaces without inverse for more. ### columnWrapperStyle columnWrapperStyle?: StyleProp<ViewStyle>; Style applied to each column’s wrapper view. ### contentContainerStyle contentContainerStyle?: StyleProp<ViewStyle>; Style applied to the underlying ScrollView’s content container. ### drawDistance drawDistance?: number; The `drawDistance` (defaults to `250`) is the buffer size in pixels above and below the viewport that will be rendered in advance. See Performance for more. extraData?: any; Extra data to trigger re-rendering when changed. See React Native Docs. ### getEstimatedItemSize getEstimatedItemSize?: (index: number, item: ItemT) => number; An estimated size for each item which is used to estimate the list layout before items actually render. If you don’t provide this, it will log a suggested value for optimal performance. ### horizontal horizontal?: boolean; // default: false Renders all items in the list in horizontal. ### initialContainerPoolRatio initialContainerPoolRatio?: number; // default: 1 Ratio of initial container pool size to data length. ### initialScrollIndex initialScrollIndex?: number; Start scrolled with this item at the top. By default, to have accurate scrolling position you will need to provide accurate element positions to the getEstimatedItemSize function(similar FlatList). When accurate positions are not known (e.g., for dynamically sized list items), please enable maintainVisibleContentPosition prop. This will allow LegendList to automatically adjust its top boundary when elements below initialScrollIndex will be measured. ### initialScrollOffset initialScrollOffset?: number; Start scrolled to this offset. ### ItemSeparatorComponent ItemSeparatorComponent?: React.ComponentType<any>; Rendered in between each item, but not at the top or bottom. See React Native Docs. ### ListEmptyComponent ListEmptyComponent?: React.ComponentType<any> | React.ReactElement | null | undefined; Rendered when the list is empty. See React Native Docs. ### ListEmptyComponentStyle ListEmptyComponentStyle?: StyleProp<ViewStyle> | undefined; Styling for internal View for `ListEmptyComponent`. ListFooterComponent?: React.ComponentType<any> | React.ReactElement | null | undefined; Rendered at the bottom of all the items. See React Native Docs. ListFooterComponentStyle?: StyleProp<ViewStyle> | undefined; Styling for internal View for `ListFooterComponent`. See React Native Docs. ListHeaderComponent?: React.ComponentType<any> | React.ReactElement | null | undefined; Rendered at the top of all the items. See React Native Docs. Styling for internal View for `ListHeaderComponent`. See React Native Docs. ### maintainScrollAtEnd maintainScrollAtEnd?: boolean; This will check if you are already scrolled to the bottom when `data` changes, and if so it keeps you scrolled to the bottom. See Chat interfaces without `inverted` for more. ### maintainScrollAtEndThreshold maintainScrollAtEndThreshold?: number; This defines what percent of the screen counts as the bottom. Defaults to `0.1`. See Chat interfaces without `inverted` for more. ### maintainVisibleContentPosition maintainVisibleContentPosition?: boolean; The `maintainVisibleContentPosition` prop automatically adjusts item positions when items are added/removed/resized above the viewport so that there is no shift in the visible content. This is very helpful for some scenarios, but if you have a static list of fixed sized items you probably don’t need it. * If items get added/removed/resized above the viewport, items will not move on screen * When using `initialScrollOffset` or `initialScrollIndex`, items will not jump around when scrolling up if they’re different sizes than the estimate * When scrolling to an index far down the list and then back up, items will not jump around as they layout LegendList utilizes ScrollView’s maintainVisibleContentPosition prop internally, so your target react-native version should support that prop. To use maintainVisibleContentPosition on Android you will need at least React Native version 0.72. ### numColumns numColumns?: number; Multiple columns will zig-zag like a flexWrap layout. Rows will take the maximum height of their columns, so items should all be the same height - masonry layouts are not supported. ### onEndReached onEndReached?: ((info: { distanceFromEnd: number }) => void) | null | undefined; A callback that’s called only once when scroll is within `onEndReachedThreshold` of the bottom of the list. It resets when scroll goes above the threshold and then will be called again when scrolling back into the threshold. ### onEndReachedThreshold onEndReachedThreshold?: number | null | undefined; The distance from the end as a percentage that the scroll should be from the end to trigger `onEndReached`. It is multiplied by screen size, so a value of 0.5 will trigger `onEndReached` when scrolling to half a screen from the end. ### onItemSizeChanged onItemSizeChanged?: (info: { size: number; previous: number; index: number; itemKey: string; itemData: ItemT; }) => void; Called whenever an item’s rendered size changes. This can be used to adjust the estimatedItemSize to match the actual size, which can improve performance or reduce layout shifting. ### onRefresh onRefresh?: () => void; Called whenever a user pulls down to refresh. See React Native Docs. ### onStartReached onStartReached?: ((info: { distanceFromStart: number }) => void) | null | undefined; A callback that’s called only once when scroll is within `onStartReachedThreshold` of the top of the list. It resets when scroll goes below the threshold and then will be called again when scrolling back into the threshold. ### onStartReachedThreshold onStartReachedThreshold?: number | null | undefined; The distance from the start as a percentage that the scroll should be from the end to trigger `onStartReached`. It is multiplied by screen size, so a value of 0.5 will trigger `onStartReached` when scrolling to half a screen from the start. ### onViewableItemsChanged onViewableItemsChanged?: OnViewableItemsChanged | undefined; Called when the viewability of rows changes, as defined by the `viewabilityConfig` prop. See React Native Docs. ### progressViewOffset progressViewOffset?: number | undefined; Offset in pixels for the refresh indicator. ### ref ref?: LegendListRef; Used to call `scrollTo` methods. ### refreshing refreshing?: boolean; Set this true while waiting for new data from a refresh. See React Native Docs. ### recycleItems recycleItems?: boolean; // default: false This will reuse the component rendered by your `renderItem` function. For more information, see Performance for more information. ### renderScrollComponent renderScrollComponent?: (props: ScrollViewProps) => ReactNode Render custom ScrollView component. Allows customization of the underlying ScrollView. ### style style?: StyleProp<ViewStyle>; Style applied to the underlying ScrollView. ### viewabilityConfig viewabilityConfig?: ViewabilityConfig; Configuration for when to update the `onViewableItemsChanged` callback. See React Native Docs. ### viewabilityConfigCallbackPairs viewabilityConfigCallbackPairs?: ViewabilityConfigCallbackPairs | undefined; List of `ViewabilityConfig`/`onViewableItemsChanged` pairs. A specific `onViewableItemsChanged` will be called when its corresponding `ViewabilityConfig`’s conditions are met. See React Native Docs. ### waitForInitialLayout waitForInitialLayout?: boolean; // default false If true, delays rendering until initial layout is complete ## Ref Methods * * * ### scrollToIndex scrollToIndex: (params: { index: number; animated?: boolean;}); Scrolls to the item at the specified index. By default (maintainVisibleContentPosition is false), accurate scroll is guaranteed only if all accurate sizes of elements are provided to getEstimatedItemSize function(similar FlatList). If estimated item sizes are not known, maintainVisibleContentPosition prop need to be set to true. In this mode, list would automatically select element you are scrolling to as anchor element and guarantee accurate scroll. ### scrollToOffset scrollToOffset(params: { offset: number; animated?: boolean;}); Scroll to a specific content pixel offset in the list. Valid parameters: * _offset_ (number) - The offset to scroll to. In case of horizontal being true, the offset is the x-value, in any other case the offset is the y-value. Required. * _animated_ (boolean) - Whether the list should do an animation while scrolling. Defaults to true. ### scrollToItem scrollToItem(params: { animated?: ?boolean, item: Item,}); Requires linear scan through data - use scrollToIndex instead if possible. Provided for compatibility with FlatList only. Valid parameters: * _animated_ (boolean) - Whether the list should do an animation while scrolling. Defaults to true. * _item_ (object) - The item to scroll to. Required. ### scrollToEnd scrollToEnd(params?: { animated?: boolean,}); Scrolls to the end of the list. Valid parameters: * _animated_ (boolean) - Whether the list should do an animation while scrolling. Defaults to true. ## Hooks * * * ### Recycling hooks useRecyclingEffect: (effect: (info: LegendListRecyclingState) => void | (() => void)) => void;useRecyclingState: <T>(updateState: ((info: LegendListRecyclingState) => T) | T) => [T, Dispatch<T>]; `renderItem` receives two hooks to help you manage the recycling. 1. `useRecyclingState` automatically resets the state when it recycles into a new item 2. `useRecyclingEffect` can be used to reset any side effects when an item gets recycled. export function ItemComponent({ item, useRecyclingEffect, useRecyclingState }) { // Like useState but it resets when the item is recycled const [isExpanded, setIsExpanded] = useRecyclingState(() => false); // A callback when the item is recycled into a new item useRecyclingEffect?.(({ item, prevItem, index, prevIndex }) => { // Reset any side effects from the previous item refSwipeable?.current?.close(); refVideo?.current?.reset(); }); // ...} --- ## Page: https://legendapp.com/open-source/list/api/performance/ Legend List is very optimized by default, so it may already be working well without any configuration. But these are some common ways to improve your list behavior. It’s important to provide an `estimatedItemSize` (if items are the same size or all dynamic sizes) or `getEstimatedItemSize` (if items are different known sizes). Legend List uses this as the default item size, then as items are rendered it updates their positions with the actual size. So getting this estimate as close as possible to the real size will reduce layout shifting and blank spaces as items render. If not provided it will use `100px` as the default. The `onItemSizeChanged` event can also help with your estimations - it will be called whenever an item’s size changes. So you can use it to log what the actual rendered size is to adjust your estimates. keyExtractor?: (item: T, index: number) => string; The `keyExtractor` prop lets Legend List save item layouts by key, so that if the `data` array changes it can reuse previous layout information and only update the changed items. Without `keyExtractor`, item sizes will reset to their default whenever `data` changes. So it is _very recommended_ to have a `keyExtractor` if `data` ever changes. If your items are a fixed size, providing a `keyExtractor` that returns the index will tell it to reuse size information. ### Recycling List Items recycleItems?: boolean // default: false Legend List has an optional `recycleItems` prop which enables view recycling. This will reuse the component rendered by your `renderItem` function. This can be a big performance optimization because it does not need to destroy/create views while scrolling. But it also reuses any local state, which can cause some weird behavior that may not be desirable depending on your app. But see the next section for recycling hooks to make that easier. So there are some tradeoffs with recycling: * 👍 If you have items with no state then recycling should be great * 👎 If you have simple items with complex state then it may be more trouble than it’s worth * 👍 If you have heavy items with complex state then working around the state recycling may be worth it for the performance gains ### Estimate Item Sizes estimatedItemSize?: number;getEstimatedItemSize?: (index: number, item: T) => number;onItemSizeChanged?: (info: { size: number; previous: number; index: number; itemKey: string; itemData: ItemT; }) => void; ### Set DrawDistance Prop drawDistance?: number The `drawDistance` (defaults to `250`) is the buffer size in pixels above and below the viewport that will be rendered in advance. So for example if your screen is `2000px` tall and your draw distance is `1000`, then it will render double your screen size, from `-1000px` above the viewport to `1000px` below the viewport. This can help reduce the amount of blank space while scrolling quickly. But if your items are computationally expensive, it may reduce performance because more items are rendering at once. So you should experiment with it to find the most optimal behavior for your app. ### Use `waitForInitialLayout` Prop waitForInitialLayout?: boolean If the size of your list items differs significantly from the estimate, you may see a layout jump after the first render. If so, the `waitForInitialLayout` prop solves that by delaying displaying list items by one frame so they start at the correct position. --- ## Page: https://legendapp.com/open-source/list/examples/chatinterfaces/ ## Chat Interfaces Without `inverted` In other list libraries if you wanted items to start scrolling from the bottom, you’d need to use an `inverted` prop, which would apply a negative scale transform. But that causes a lot of weird issues, so Legend List explicitly does not do that. alignItemsAtEnd?: boolean;maintainScrollAtEnd?: boolean;maintainScrollAtEndThreshold?: number; Instead, to align items at the end you can just use the `alignItemsAtEnd` prop, which will apply padding above items to fill the screen and stick them to the bottom. The `maintainScrollAtEnd` prop will check if you are already scrolled to the bottom when `data` changes, and if so it keeps you scrolled to the bottom. The `maintainScrollAtEndThreshold` prop (which defaults to 0.1) defines what percent of the screen counts as the bottom. So using Legend List for a chat interface would look like this: <LegendList data={items} renderItem={({ item }) => <Text>{item.title}</Text>} estimatedItemSize={320} alignItemsAtEnd maintainScrollAtEnd maintainScrollAtEndThreshold={0.1} /> --- ## Page: https://legendapp.com/open-source/list/examples/infinitescrolling/ onStartReached?: ((info: { distanceFromStart: number }) => void) | null | undefined;onEndReached?: ((info: { distanceFromEnd: number }) => void) | null | undefined; These callbacks fire when you scroll to the top or bottom of a list. This can be used to load more data in either direction. In a typical list you’ll likely just use `onEndReached` to load more data when the users scrolls to the bottom. If you have a chat-like interface you may want to load more messages as you scroll up, and you can use `onStartReached` for that. If you are doing that, you will very likely want to use maintainVisibleContentPosition so that the items loading above don’t shift the viewport down. --- ## Page: https://legendapp.com/open-source/list/plugins/placeholder/ Our goal with LegendList is to keep the main package as small as possible to benefit the most people. However, there are special use cases that some may need for their product, so we plan on supporting those with a plugin system. --- ## Page: https://legendapp.com/open-source/list/benchmarks/placeholder/ These docs are still in progress. Below are preliminary benchmarks comparing `LegendList` to `FlatList` and `FlashList`. These metrics are placeholders and will be updated with real data as testing progresses. ## Performance Benchmarks | Metric | LegendList | FlatList | FlashList | Notes | | --- | --- | --- | --- | --- | | **Initial Render Time** | XXXms | XXXms | XXXms | 1000 items, simple text render | | **Scroll FPS (60fps)** | XXfps | XXfps | XXfps | 5000 items, mixed content | | **Memory Usage** | XXMB | XXMB | XXMB | 10,000 items, images + text | | **Item Recycling** | Yes | No | Yes | Efficiency with dynamic content | | **Cold Start Time** | XXXms | XXXms | XXXms | App launch with 2000 items | | **Re-render Time** | XXms | XXms | XXms | Update 10% of 5000 items | | **CPU Usage** | XX% | XX% | XX% | Continuous scroll, 3000 items | ### Notes * **Initial Render Time**: Time to render the list on screen from a blank state. * **Scroll FPS**: Frames per second during smooth scrolling; higher is better (target 60fps). * **Memory Usage**: Peak memory consumption during list operation. * **Item Recycling**: Whether the list reuses item views for performance. * **Cold Start Time**: Time from app launch to fully rendered list. * **Re-render Time**: Time to update the list after data changes. * **CPU Usage**: Average CPU load during active scrolling. These benchmarks are based on simulated conditions (e.g., iOS 16, mid-tier device). Actual performance may vary depending on hardware, React Native version, and list content complexity. Stay tuned for finalized data! --- ## Page: https://legendapp.com/open-source/list/api/props Below is a list of all the properties for LegendList: ## Required Props * * * ### data data: ItemT[]; An array of the items to render. This can also be an array of keys if you want to get the item by key in renderItem. ### estimatedItemSize estimatedItemSize?: number; An estimated size for all items which is used to estimate the list layout before items actually render. If you don’t provide this, it will log a suggested value for optimal performance. ### renderItem renderItem?: (props: LegendListRenderItemProps<ItemT>) => ReactNode; Takes an item from data and renders it into the list. See React Native Docs. ## Recommended Props * * * keyExtractor?: (item: ItemT, index: number) => string; Highly recommended. The `keyExtractor` prop lets Legend List save item layouts by key, so that if the `data` array changes it can reuse previous layout information and only update the changed items. See Use key extractor. If LegendList detects duplicate keys, it will log a warning. ## Optional Props * * * ### alignItemsAtEnd alignItemsAtEnd?: boolean; // default: false Aligns to the end of the screen, so if there’s only a few items there will be enough padding at the top to make them appear to be at the bottom. See Chat interfaces without inverse for more. ### columnWrapperStyle columnWrapperStyle?: StyleProp<ViewStyle>; Style applied to each column’s wrapper view. ### contentContainerStyle contentContainerStyle?: StyleProp<ViewStyle>; Style applied to the underlying ScrollView’s content container. ### drawDistance drawDistance?: number; The `drawDistance` (defaults to `250`) is the buffer size in pixels above and below the viewport that will be rendered in advance. See Performance for more. extraData?: any; Extra data to trigger re-rendering when changed. See React Native Docs. ### getEstimatedItemSize getEstimatedItemSize?: (index: number, item: ItemT) => number; An estimated size for each item which is used to estimate the list layout before items actually render. If you don’t provide this, it will log a suggested value for optimal performance. ### horizontal horizontal?: boolean; // default: false Renders all items in the list in horizontal. ### initialContainerPoolRatio initialContainerPoolRatio?: number; // default: 1 Ratio of initial container pool size to data length. ### initialScrollIndex initialScrollIndex?: number; Start scrolled with this item at the top. By default, to have accurate scrolling position you will need to provide accurate element positions to the getEstimatedItemSize function(similar FlatList). When accurate positions are not known (e.g., for dynamically sized list items), please enable maintainVisibleContentPosition prop. This will allow LegendList to automatically adjust its top boundary when elements below initialScrollIndex will be measured. ### initialScrollOffset initialScrollOffset?: number; Start scrolled to this offset. ### ItemSeparatorComponent ItemSeparatorComponent?: React.ComponentType<any>; Rendered in between each item, but not at the top or bottom. See React Native Docs. ### ListEmptyComponent ListEmptyComponent?: React.ComponentType<any> | React.ReactElement | null | undefined; Rendered when the list is empty. See React Native Docs. ### ListEmptyComponentStyle ListEmptyComponentStyle?: StyleProp<ViewStyle> | undefined; Styling for internal View for `ListEmptyComponent`. ListFooterComponent?: React.ComponentType<any> | React.ReactElement | null | undefined; Rendered at the bottom of all the items. See React Native Docs. ListFooterComponentStyle?: StyleProp<ViewStyle> | undefined; Styling for internal View for `ListFooterComponent`. See React Native Docs. ListHeaderComponent?: React.ComponentType<any> | React.ReactElement | null | undefined; Rendered at the top of all the items. See React Native Docs. Styling for internal View for `ListHeaderComponent`. See React Native Docs. ### maintainScrollAtEnd maintainScrollAtEnd?: boolean; This will check if you are already scrolled to the bottom when `data` changes, and if so it keeps you scrolled to the bottom. See Chat interfaces without `inverted` for more. ### maintainScrollAtEndThreshold maintainScrollAtEndThreshold?: number; This defines what percent of the screen counts as the bottom. Defaults to `0.1`. See Chat interfaces without `inverted` for more. ### maintainVisibleContentPosition maintainVisibleContentPosition?: boolean; The `maintainVisibleContentPosition` prop automatically adjusts item positions when items are added/removed/resized above the viewport so that there is no shift in the visible content. This is very helpful for some scenarios, but if you have a static list of fixed sized items you probably don’t need it. * If items get added/removed/resized above the viewport, items will not move on screen * When using `initialScrollOffset` or `initialScrollIndex`, items will not jump around when scrolling up if they’re different sizes than the estimate * When scrolling to an index far down the list and then back up, items will not jump around as they layout LegendList utilizes ScrollView’s maintainVisibleContentPosition prop internally, so your target react-native version should support that prop. To use maintainVisibleContentPosition on Android you will need at least React Native version 0.72. ### numColumns numColumns?: number; Multiple columns will zig-zag like a flexWrap layout. Rows will take the maximum height of their columns, so items should all be the same height - masonry layouts are not supported. ### onEndReached onEndReached?: ((info: { distanceFromEnd: number }) => void) | null | undefined; A callback that’s called only once when scroll is within `onEndReachedThreshold` of the bottom of the list. It resets when scroll goes above the threshold and then will be called again when scrolling back into the threshold. ### onEndReachedThreshold onEndReachedThreshold?: number | null | undefined; The distance from the end as a percentage that the scroll should be from the end to trigger `onEndReached`. It is multiplied by screen size, so a value of 0.5 will trigger `onEndReached` when scrolling to half a screen from the end. ### onItemSizeChanged onItemSizeChanged?: (info: { size: number; previous: number; index: number; itemKey: string; itemData: ItemT; }) => void; Called whenever an item’s rendered size changes. This can be used to adjust the estimatedItemSize to match the actual size, which can improve performance or reduce layout shifting. ### onRefresh onRefresh?: () => void; Called whenever a user pulls down to refresh. See React Native Docs. ### onStartReached onStartReached?: ((info: { distanceFromStart: number }) => void) | null | undefined; A callback that’s called only once when scroll is within `onStartReachedThreshold` of the top of the list. It resets when scroll goes below the threshold and then will be called again when scrolling back into the threshold. ### onStartReachedThreshold onStartReachedThreshold?: number | null | undefined; The distance from the start as a percentage that the scroll should be from the end to trigger `onStartReached`. It is multiplied by screen size, so a value of 0.5 will trigger `onStartReached` when scrolling to half a screen from the start. ### onViewableItemsChanged onViewableItemsChanged?: OnViewableItemsChanged | undefined; Called when the viewability of rows changes, as defined by the `viewabilityConfig` prop. See React Native Docs. ### progressViewOffset progressViewOffset?: number | undefined; Offset in pixels for the refresh indicator. ### ref ref?: LegendListRef; Used to call `scrollTo` methods. ### refreshing refreshing?: boolean; Set this true while waiting for new data from a refresh. See React Native Docs. ### recycleItems recycleItems?: boolean; // default: false This will reuse the component rendered by your `renderItem` function. For more information, see Performance for more information. ### renderScrollComponent renderScrollComponent?: (props: ScrollViewProps) => ReactNode Render custom ScrollView component. Allows customization of the underlying ScrollView. ### style style?: StyleProp<ViewStyle>; Style applied to the underlying ScrollView. ### viewabilityConfig viewabilityConfig?: ViewabilityConfig; Configuration for when to update the `onViewableItemsChanged` callback. See React Native Docs. ### viewabilityConfigCallbackPairs viewabilityConfigCallbackPairs?: ViewabilityConfigCallbackPairs | undefined; List of `ViewabilityConfig`/`onViewableItemsChanged` pairs. A specific `onViewableItemsChanged` will be called when its corresponding `ViewabilityConfig`’s conditions are met. See React Native Docs. ### waitForInitialLayout waitForInitialLayout?: boolean; // default false If true, delays rendering until initial layout is complete ## Ref Methods * * * ### scrollToIndex scrollToIndex: (params: { index: number; animated?: boolean;}); Scrolls to the item at the specified index. By default (maintainVisibleContentPosition is false), accurate scroll is guaranteed only if all accurate sizes of elements are provided to getEstimatedItemSize function(similar FlatList). If estimated item sizes are not known, maintainVisibleContentPosition prop need to be set to true. In this mode, list would automatically select element you are scrolling to as anchor element and guarantee accurate scroll. ### scrollToOffset scrollToOffset(params: { offset: number; animated?: boolean;}); Scroll to a specific content pixel offset in the list. Valid parameters: * _offset_ (number) - The offset to scroll to. In case of horizontal being true, the offset is the x-value, in any other case the offset is the y-value. Required. * _animated_ (boolean) - Whether the list should do an animation while scrolling. Defaults to true. ### scrollToItem scrollToItem(params: { animated?: ?boolean, item: Item,}); Requires linear scan through data - use scrollToIndex instead if possible. Provided for compatibility with FlatList only. Valid parameters: * _animated_ (boolean) - Whether the list should do an animation while scrolling. Defaults to true. * _item_ (object) - The item to scroll to. Required. ### scrollToEnd scrollToEnd(params?: { animated?: boolean,}); Scrolls to the end of the list. Valid parameters: * _animated_ (boolean) - Whether the list should do an animation while scrolling. Defaults to true. ## Hooks * * * ### Recycling hooks useRecyclingEffect: (effect: (info: LegendListRecyclingState) => void | (() => void)) => void;useRecyclingState: <T>(updateState: ((info: LegendListRecyclingState) => T) | T) => [T, Dispatch<T>]; `renderItem` receives two hooks to help you manage the recycling. 1. `useRecyclingState` automatically resets the state when it recycles into a new item 2. `useRecyclingEffect` can be used to reset any side effects when an item gets recycled. export function ItemComponent({ item, useRecyclingEffect, useRecyclingState }) { // Like useState but it resets when the item is recycled const [isExpanded, setIsExpanded] = useRecyclingState(() => false); // A callback when the item is recycled into a new item useRecyclingEffect?.(({ item, prevItem, index, prevIndex }) => { // Reset any side effects from the previous item refSwipeable?.current?.close(); refVideo?.current?.reset(); }); // ...} --- ## Page: https://legendapp.com/open-source/list/api/performance#set-drawdistance-prop Legend List is very optimized by default, so it may already be working well without any configuration. But these are some common ways to improve your list behavior. It’s important to provide an `estimatedItemSize` (if items are the same size or all dynamic sizes) or `getEstimatedItemSize` (if items are different known sizes). Legend List uses this as the default item size, then as items are rendered it updates their positions with the actual size. So getting this estimate as close as possible to the real size will reduce layout shifting and blank spaces as items render. If not provided it will use `100px` as the default. The `onItemSizeChanged` event can also help with your estimations - it will be called whenever an item’s size changes. So you can use it to log what the actual rendered size is to adjust your estimates. keyExtractor?: (item: T, index: number) => string; The `keyExtractor` prop lets Legend List save item layouts by key, so that if the `data` array changes it can reuse previous layout information and only update the changed items. Without `keyExtractor`, item sizes will reset to their default whenever `data` changes. So it is _very recommended_ to have a `keyExtractor` if `data` ever changes. If your items are a fixed size, providing a `keyExtractor` that returns the index will tell it to reuse size information. ### Recycling List Items recycleItems?: boolean // default: false Legend List has an optional `recycleItems` prop which enables view recycling. This will reuse the component rendered by your `renderItem` function. This can be a big performance optimization because it does not need to destroy/create views while scrolling. But it also reuses any local state, which can cause some weird behavior that may not be desirable depending on your app. But see the next section for recycling hooks to make that easier. So there are some tradeoffs with recycling: * 👍 If you have items with no state then recycling should be great * 👎 If you have simple items with complex state then it may be more trouble than it’s worth * 👍 If you have heavy items with complex state then working around the state recycling may be worth it for the performance gains ### Estimate Item Sizes estimatedItemSize?: number;getEstimatedItemSize?: (index: number, item: T) => number;onItemSizeChanged?: (info: { size: number; previous: number; index: number; itemKey: string; itemData: ItemT; }) => void; ### Set DrawDistance Prop drawDistance?: number The `drawDistance` (defaults to `250`) is the buffer size in pixels above and below the viewport that will be rendered in advance. So for example if your screen is `2000px` tall and your draw distance is `1000`, then it will render double your screen size, from `-1000px` above the viewport to `1000px` below the viewport. This can help reduce the amount of blank space while scrolling quickly. But if your items are computationally expensive, it may reduce performance because more items are rendering at once. So you should experiment with it to find the most optimal behavior for your app. ### Use `waitForInitialLayout` Prop waitForInitialLayout?: boolean If the size of your list items differs significantly from the estimate, you may see a layout jump after the first render. If so, the `waitForInitialLayout` prop solves that by delaying displaying list items by one frame so they start at the correct position. --- ## Page: https://legendapp.com/open-source/list/examples/chatinterfaces ## Chat Interfaces Without `inverted` In other list libraries if you wanted items to start scrolling from the bottom, you’d need to use an `inverted` prop, which would apply a negative scale transform. But that causes a lot of weird issues, so Legend List explicitly does not do that. alignItemsAtEnd?: boolean;maintainScrollAtEnd?: boolean;maintainScrollAtEndThreshold?: number; Instead, to align items at the end you can just use the `alignItemsAtEnd` prop, which will apply padding above items to fill the screen and stick them to the bottom. The `maintainScrollAtEnd` prop will check if you are already scrolled to the bottom when `data` changes, and if so it keeps you scrolled to the bottom. The `maintainScrollAtEndThreshold` prop (which defaults to 0.1) defines what percent of the screen counts as the bottom. So using Legend List for a chat interface would look like this: <LegendList data={items} renderItem={({ item }) => <Text>{item.title}</Text>} estimatedItemSize={320} alignItemsAtEnd maintainScrollAtEnd maintainScrollAtEndThreshold={0.1} />