Skip to content

useInfiniteScroll

Loads the next result chunk when a scroll target reaches its edge.

Loads the next result chunk when a scroll target reaches its edge.

Import

import { useInfiniteScroll } from '@kamod-ch/hooks'

Live demo

Basic demo

Loads the next result chunk when a scroll target reaches its edge.

Browser-only demo

This demo starts after the page mounts in the browser.
import { useRef } from 'preact/hooks'
import { useInfiniteScroll } from '@kamod-ch/hooks'

const total = 18
async function load(current?: { list: string[]; cursor: number }) {
  await new Promise((resolve) => window.setTimeout(resolve, 300))
  const cursor = current?.cursor ?? 0
  const next = Array.from({ length: 6 }, (_, index) => 'Item ' + (cursor + index + 1))
  return { list: next, cursor: cursor + next.length }
}

export default function UseInfiniteScrollDemo() {
  const ref = useRef<HTMLDivElement>(null)
  const result = useInfiniteScroll(load, {
    target: ref,
    isNoMore: (data) => (data?.cursor ?? 0) >= total
  })

  return (
    <div>
      <div ref={ref} class="demo-scroll-box">
        {(result.data?.list ?? []).map((item) => <p key={item}>{item}</p>)}
        <p>{result.loadingMore ? 'Loading more…' : result.noMore ? 'No more items.' : 'Scroll to the bottom.'}</p>
      </div>
      <button type="button" onClick={result.reload}>Reload</button>
    </div>
  )
}

API

TypeScript signature
import type { Data, InfiniteScrollOptions, Service } from './types.js';
declare const useInfiniteScroll: <TData extends Data>(service: Service<TData>, options?: InfiniteScrollOptions<TData>) => {
    data: TData;
    loading: boolean;
    error: Error;
    loadingMore: boolean;
    noMore: boolean;
    loadMore: (this: unknown) => void;
    loadMoreAsync: (this: unknown) => Promise<TData>;
    reload: (this: unknown) => void;
    reloadAsync: (this: unknown) => Promise<TData>;
    mutate: import("preact/hooks").Dispatch<import("preact/hooks").StateUpdater<TData>>;
    cancel: () => void;
};
export default useInfiniteScroll;
/

SSR considerations

This hook touches browser APIs. Render it after mount or guard it with BrowserOnly in SSR and static builds.

Browser compatibility

Requires the corresponding browser API to exist in the current environment.

Related hooks