Skip to content

Instantly share code, notes, and snippets.

@naqvitalha
Last active May 29, 2025 21:40
Show Gist options
  • Save naqvitalha/cdaf87ef531fdd3cd0f26352b8ef770d to your computer and use it in GitHub Desktop.
Save naqvitalha/cdaf87ef531fdd3cd0f26352b8ef770d to your computer and use it in GitHub Desktop.
A LazyScrollView built using FlashList v2
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