Skip to content

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.

renderItem

renderItem?: (props: LegendListRenderItemProps<ItemT>) => ReactNode;

Takes an item from data and renders it into the list.

See React Native Docs.


keyExtractor

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. The value it returns should be unique to each item - if a value is reused for a different item it will cause big problems. It is okay to return the index, if list items are reordered or prepended, it will also cause big problems. See Use key extractor.

If LegendList detects duplicate keys, it will log a warning.

recycleItems

recycleItems?: boolean; // default: false

This will reuse the component rendered by your renderItem function. This can be a big performance improvement, but if your list items have internal state there’s potential for undesirable behavior. For more information, see Performance for more information.

estimatedItemSize

estimatedItemSize?: number;

An estimated size for all items which is used to estimate the list layout before items actually render. This can help to provide a hint for how large items will be in the first frame and can speed up initial layout, but subsequent renders will use the average item size.

Optional Props


alignItemsAtEnd

alignItemsAtEnd?: boolean; // default: false

Aligns to the end of the screen. If there’s only a few items, Legend List will add padding to the top to align them to 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

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: 2

Ratio of initial container pool size to data length. The container pool is extra unallocated containers that are used in case the actual size is smaller than the estimated size. This defaults to 2 which we’ve found to cover most usage. If your items are a fixed size you could set it closer to 1, or if your items or viewport can resize signficantly it may help to increase it. If the number of containers needed exceeds the pool, LegendList will allocate more containers and re-render the outer list, which may cause a frame stutter.

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<{ leadingItem: ItemT }>

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

ListFooterComponent?: React.ComponentType<any> | React.ReactElement | null | undefined;

Rendered at the bottom of all the items.

See React Native Docs.

ListFooterComponentStyle

ListFooterComponentStyle?: StyleProp<ViewStyle> | undefined;

Styling for internal View for ListFooterComponent.

See React Native Docs.

ListHeaderComponent

ListHeaderComponent?: React.ComponentType<any> | React.ReactElement | null | undefined;

Rendered at the top of all the items.

See React Native Docs.

ListHeaderComponentStyle

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.

renderScrollComponent

renderScrollComponent?: (props: ScrollViewProps) => ReactNode

Render a custom ScrollView component. This allows customization of the underlying ScrollView.

Note that passing renderScrollComponent as an inline function might cause you to lose scroll position if the list is rerendered.

renderScrollComponent={(props) => <BottomSheetScrollView {...props} />}

Instead, it’s better to extract it as a custom component.

const CustomScrollView = (props: ScrollViewProps) => {
return <BottomSheetScrollView {...props} />;
};

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


getState

getState: () => {
contentLength: number;
end: number;
endBuffered: number;
isAtEnd: boolean;
isAtStart: boolean;
scroll: number;
scrollLength: number;
start: number;
startBuffered: number;
}

Returns the internal scroll state of the list.

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.

scrollIndexIntoView

Scrolls the index into view. If the index is above the viewable range it will be scrolled to the top of the screen, and if it’s below the viewable range it will be scrolled to the bottom of the screen.

scrollIndexIntoView(params: {
animated?: boolean | undefined;
index: number;
}): void
import { LegendList } from "@legendapp/list";
import { useRef } from "react";
export function ScrollExample() {
const listRef = useRef(null);
const scrollToItem = () => {
// Scroll to the item at index 10
listRef.current?.scrollIndexIntoView(10);
};
return (
<>
<Button title="Scroll to item 10" onPress={scrollToItem} />
<LegendList
ref={listRef}
data={data}
renderItem={renderItem}
/>
</>
);
}

scrollItemIntoView

Scrolls the item into view. If the item is above the viewable range it will be scrolled to the top of the screen, and if it’s below the viewable range it will be scrolled to the bottom of the screen.

scrollItemIntoView(params: {
animated?: boolean | undefined;
item: any;
}): void;
import { LegendList } from "@legendapp/list";
import { useRef } from "react";
export function ScrollToItemExample() {
const listRef = useRef(null);
const targetItem = { id: "item-5", text: "Target Item" };
const scrollToSpecificItem = () => {
// Scroll to the item that matches targetItem
listRef.current?.scrollItemIntoView(targetItem);
};
return (
<>
<Button title="Scroll to target item" onPress={scrollToSpecificItem} />
<LegendList
ref={listRef}
data={data}
renderItem={renderItem}
/>
</>
);
}

Hooks

useRecyclingState

interface LegendListRecyclingState<T> {
item: T;
prevItem: T | undefined;
index: number;
prevIndex: number | undefined;
}
useRecyclingState: <T>(updateState: ((info: LegendListRecyclingState<T>) => T) | T) => [T, Dispatch<T>];

useRecyclingState automatically resets the state when an item is recycled into a new item.

import { useRecyclingState } from "@legendapp/list"
export function ItemComponent({ item }) {
// Like useState but it resets when the item is recycled
const [isExpanded, setIsExpanded] = useRecyclingState(() => false);
// ...
}

useRecyclingEffect

interface LegendListRecyclingState<T> {
item: T;
prevItem: T | undefined;
index: number;
prevIndex: number | undefined;
}
useRecyclingEffect: <T>(effect: (info: LegendListRecyclingState<T>) => void | (() => void)) => void;

useRecyclingEffect can be used to reset any side effects when an item gets recycled.

import { useRecyclingEffect } from "@legendapp/list"
export function ItemComponent({ item, useRecyclingEffect }) {
// 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();
});
// ...
}

useViewability

interface ViewToken<ItemT = any> {
containerId: number;
index: number;
isViewable: boolean;
item: ItemT;
key: string;
}
useViewability: (configId: string, callback: (viewToken: ViewToken) => void) => void;

A hook that provides callbacks when an item’s viewability changes. This hook registers a callback that will be invoked whenever the item’s visibility status changes, providing detailed information about the item through the ViewToken interface. It is similar to onViewableItemsChanged but runs for only the rendering item. If you defined multiple viewability configs using viewabilityConfigCallbackPairs then provide the id of the one you’re interested in with configId.

import { useViewability } from "@legendapp/list"
export function ItemComponent({ item }) {
const [isVisible, setIsVisible] = useState(false);
useViewability((viewToken) => {
// Called when viewability changes
setIsVisible(viewToken.isViewable);
if (viewToken.isViewable) {
console.log("Item visible:", viewToken.item);
console.log("Item index:", viewToken.index);
}
}, "main");
return (
<View>
{isVisible ? <ExpensiveComponent /> : <PlaceholderComponent />}
</View>
);
}

useViewabilityAmount

interface ViewAmountToken<ItemT = any> {
containerId: number;
index: number;
isViewable: boolean;
item: ItemT;
key: string;
percentOfScroller: number;
percentVisible: number;
scrollSize: number;
size: number;
sizeVisible: number;
}
useViewabilityAmount: (callback: (viewAmountToken: ViewAmountToken) => void) => void;

A hook that provides detailed metrics about how much of an item is visible in the viewport. The callback receives a ViewAmountToken with information like the pixel measurements (sizeVisible, size), percentage visible, and more.

import { useViewabilityAmount } from "@legendapp/list"
export function ItemComponent({ item }) {
const [opacity, setOpacity] = useState(0);
useViewabilityAmount((viewAmountToken) => {
// Get detailed visibility information
setOpacity(viewAmountToken.percentVisible);
// Additional metrics available:
// viewAmountToken.sizeVisible - pixels of item visible in viewport
// viewAmountToken.size - total size of the item
// viewAmountToken.percentOfScroller - what percent of the scroller this item takes up
// viewAmountToken.scrollSize - size of the viewport
});
return (
<Animated.View style={{ opacity }}>
<Text>{item.title}</Text>
</Animated.View>
);
}