Skip to content
kaskaid

useEndReached

Infinite-loading trigger

A small, fetching-agnostic hook that fires a callback once the last rendered item nears the end of your loaded data. It never fetches anything itself — you wire the callback to whatever data layer you use (TanStack Query, SWR, Apollo, a raw loader). It pairs with useMasonry but works with any { index }[] list.

The <Masonry> component wires this hook internally via its onEndReached prop. For end-to-end examples of both flavors, see the Infinite Loading guide.

function useEndReached(
  items: Pick<VirtualItem, 'index'>[],
  dataLength: number,
  onEndReached: () => void,
  options?: UseEndReachedOptions // { threshold?: number; disabled?: boolean }
): void;

Parameters

items

  • Type: Pick<VirtualItem, 'index'>[]

The rendered items — pass useMasonry().items. The hook only reads .index of the last entry.

dataLength

  • Type: number

The length of your full data array. The trigger compares the last rendered index against this.

onEndReached

  • Type: () => void

Called when the last rendered index reaches the threshold. Fetching-agnostic — the hook never fetches; pass your loader (fetchNextPage, setSize, fetchMore) directly.

options.threshold

  • Type: number
  • Default: 0

How close the last rendered index may get to the end of dataLength before firing. 0 fires once the final item of data actually renders.

options.disabled

  • Type: boolean
  • Default: false

Hard-suppresses firing. Wire it to your in-flight / has-more state (isFetchingNextPage, !hasNextPage) — the hook does not track fetch state itself.

Notes

The hook depends on the last rendered index (a primitive), not the items array, because useMasonry().items has a fresh identity every render — depending on the array would re-run the effect every render. Batched range-loading and sparse (isItemLoaded) loading are intentionally out of scope; compose them yourself if a large overscan or slow network needs them.