Last active
May 29, 2025 21:40
-
-
Save naqvitalha/cdaf87ef531fdd3cd0f26352b8ef770d to your computer and use it in GitHub Desktop.
A LazyScrollView built using FlashList v2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Children, forwardRef} from 'react'; | |
import type {ForwardedRef,JSX} from 'react'; | |
import type {ScrollViewProps} from 'react-native'; | |
import type {FlashListProps} from '@shopify/flash-list'; | |
import {FlashList} from '@shopify/flash-list'; | |
import isArray from 'lodash/isArray'; | |
/** | |
* Props for the `LazyScrollView` component. Please note that the children should be flat for this to be performant. | |
* Don't nest children inside other components. | |
*/ | |
export interface LazyScrollViewProps extends ScrollViewProps { | |
/** | |
* If enabled, `LazyScrollView` will try to reuse views that are no longer visible. | |
* Recycling isn't guaranteed, in most cases children will be destroyed and recreated. | |
* If items are heterogeneous, this will be a a lot slower when compared to `FlashList`. | |
*/ | |
virtualize?: boolean; | |
contentContainerStyle?: FlashListProps<unknown>['contentContainerStyle']; | |
} | |
/** | |
* Faster replacement for `ScrollView` that only renders visible items when it mounts. | |
* Renders buffer / remaining children lazily and has opt in virtualization. | |
* This is not a `FlashList` replacement, in most cases you should use `FlashList` directly. | |
* | |
* How to use: | |
* - Use like a `ScrollView` and render children as usual. | |
* - `FlashList` will give a warning about missing `estimatedItemSize` if it's not provided and a recommended value. | |
* - Provide the recommended value as `estimatedItemSize`. | |
*/ | |
export const LazyScrollView = forwardRef(function LazyScrollView( | |
props: LazyScrollViewProps, | |
ref: ForwardedRef<FlashList<unknown[]>>, | |
): JSX.Element { | |
const {children, virtualize} = | |
props; | |
const data = isArray(children) ? children : Children.toArray(children); | |
// Using a high number when there's no virtualization | |
// No specific reason for 2000, just a big number. Roughly 2x the screen size | |
const drawDistance = virtualize ? undefined : 2000; | |
return ( | |
<FlashList | |
ref={ref} | |
{...props} | |
data={data} | |
renderItem={({item}) => item} | |
getItemType={(_, index) => { | |
// Disables recycling of items by assigning a unique type to each item | |
// Virtualization can be enabled using `virtualize` prop but it'll not be very efficient | |
return virtualize ? undefined : index; | |
}} | |
drawDistance={drawDistance} | |
/> | |
); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment