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.
Use keyExtractor
Prop
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 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, itemType?: string) => number;getFixedItemSize?: (index: number, item: T, itemType?: string) => number | undefined; // (v2)onItemSizeChanged?: (info: { size: number; previous: number; index: number; itemKey: string; itemData: ItemT; }) => void;
Providing accurate item size estimates helps improve smooth scrolling and prevent layout shifts. estimatedItemSize
is used only for the first render, then Legend List switches to using the average of actually rendered item sizes. If you provide getEstimatedItemSize
, it will use that function instead of averages. Use getFixedItemSize
(v2) when you know exact sizes for certain item types. The more accurate your initial estimates, the better the first render experience.
Use onItemSizeChanged
to log actual vs estimated sizes and improve your estimates over time. It’s generally better to slightly underestimate than overestimate item sizes. Without estimates, Legend List defaults to 100px which will likely cause scrollbar jumping and layout issues.
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.