Hooks
usePages
Bidirectional paginated data fetching with infinite scroll support
For usage patterns and examples, see the Infinite Queries guide.
Basic Usage
Given an API that returns:
{
"items": [
{ "id": 1, "title": "Post 1" },
{ "id": 2, "title": "Post 2" }
],
"meta": { "page": 1, "hasMore": true }
}function PostList() {
const { data, loading, canFetchNext, fetchNext, fetchingNext } =
usePages(
(api) => api("posts").GET({ query: { page: 1, limit: 20 } }),
{
canFetchNext: ({ lastPage }) => lastPage?.data?.meta.hasMore ?? false,
nextPageRequest: ({ lastPage }) => ({
query: { page: (lastPage?.data?.meta.page ?? 0) + 1 },
}),
merger: (pages) => pages.flatMap((p) => p.data?.items ?? []),
}
);
if (loading) return <div>Loading...</div>;
return (
<div>
{data?.map((post) => <PostCard key={post.id} post={post} />)}
{canFetchNext && (
<button onClick={fetchNext} disabled={fetchingNext}>
{fetchingNext ? "Loading..." : "Load More"}
</button>
)}
</div>
);
}Options
| Option | Type | Required | Description |
|---|---|---|---|
merger | (pages) => TItem[] | Yes | Merge all pages into items |
canFetchNext | (ctx) => boolean | No | Check if next page exists. Default: () => false |
nextPageRequest | (ctx) => Partial<TRequest> | No | Build request for next page |
canFetchPrev | (ctx) => boolean | No | Check if previous page exists |
prevPageRequest | (ctx) => Partial<TRequest> | No | Build request for previous page |
enabled | boolean | No | Whether to fetch automatically |
Context Object
// For canFetchNext and nextPageRequest
type NextContext<TData, TRequest> = {
lastPage: InfinitePage<TData> | undefined;
pages: InfinitePage<TData>[];
request: TRequest;
};
// For canFetchPrev and prevPageRequest
type PrevContext<TData, TRequest> = {
firstPage: InfinitePage<TData> | undefined;
pages: InfinitePage<TData>[];
request: TRequest;
};
// Each page in the pages array
type InfinitePage<TData> = {
status: "pending" | "loading" | "success" | "error" | "stale";
data?: TData;
error?: TError;
meta?: TMeta;
input?: { query?; params?; body? };
};Returns
| Property | Type | Description |
|---|---|---|
data | TItem[] | undefined | Merged items from all pages |
pages | InfinitePage<TData>[] | Array of all pages with status, data, and meta |
loading | boolean | True during initial load |
fetching | boolean | True during any fetch |
fetchingNext | boolean | True while fetching next page |
fetchingPrev | boolean | True while fetching previous |
canFetchNext | boolean | Whether next page exists |
canFetchPrev | boolean | Whether previous page exists |
fetchNext | () => Promise<void> | Fetch the next page |
fetchPrev | () => Promise<void> | Fetch the previous page |
trigger | (options?) => Promise<void> | Trigger fetch with optional new request options |
abort | () => void | Abort current request |
error | TError | undefined | Error if request failed |