Skip to main content

useInfiniteScroll

Handles infinite scrolling with IntersectionObserver. Attach the returned refs to a scroll container and a loader element - the hook triggers onLoadMore when the loader becomes visible. Used internally by Select and Dropdown.Section.

Import

import { useInfiniteScroll } from '@andrejground/lab';

Usage

import React from 'react';
import { useInfiniteScroll } from '@andrejground/lab';

export default function App() {
const [items, setItems] = React.useState(Array.from({ length: 20 }, (_, i) => i));
const [hasMore, setHasMore] = React.useState(true);

const [loaderRef, scrollContainerRef] = useInfiniteScroll({
hasMore,
onLoadMore: () => {
setItems((prev) => {
const next = [...prev, ...Array.from({ length: 10 }, (_, i) => prev.length + i)];
if (next.length >= 100) setHasMore(false);
return next;
});
},
});

return (
<div ref={scrollContainerRef} style={{ height: 300, overflow: 'auto' }}>
{items.map((item) => (
<div key={item} style={{ padding: 8 }}>Item {item}</div>
))}
{hasMore && <div ref={loaderRef}>Loading...</div>}
</div>
);
}

API

const [loaderRef, scrollContainerRef] = useInfiniteScroll(options);

Options

PropertyTypeDefaultDescription
hasMorebooleantrueWhether more items can be loaded. Observer disconnects when false.
onLoadMore() => void-Callback fired when the loader element enters the viewport
isEnabledbooleantrueEnable/disable the hook
distancenumber50Root margin in pixels before the loader triggers
shouldUseLoaderbooleantrueUse loader element (true) or scroll position detection (false)
optionsOverrideIntersectionObserverInit-Override the IntersectionObserver options

Returns

IndexTypeDescription
[0]RefObjectRef to attach to the loader element
[1]RefObjectRef to attach to the scroll container