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
| Property | Type | Default | Description |
|---|---|---|---|
hasMore | boolean | true | Whether more items can be loaded. Observer disconnects when false. |
onLoadMore | () => void | - | Callback fired when the loader element enters the viewport |
isEnabled | boolean | true | Enable/disable the hook |
distance | number | 50 | Root margin in pixels before the loader triggers |
shouldUseLoader | boolean | true | Use loader element (true) or scroll position detection (false) |
optionsOverride | IntersectionObserverInit | - | Override the IntersectionObserver options |
Returns
| Index | Type | Description |
|---|---|---|
[0] | RefObject | Ref to attach to the loader element |
[1] | RefObject | Ref to attach to the scroll container |