Table of Contents

Paging

Arc supports server-side paging for query proxies when the backend query returns IQueryable<T>.

How Paging Works

When the backend returns IQueryable<T>, the query pipeline applies .Skip() and .Take() on the server so only the requested page is fetched. Generated proxies expose useWithPaging and useSuspenseWithPaging for this flow.

For backend implementation details, see Controller-based Paging and Model-bound Paging.

Enabling Paging

Use useWithPaging instead of use, passing a page size:

export const AccountList = () => {
    const [result, perform, setSorting, setPage, setPageSize] = AllAccounts.useWithPaging(25);

    return (
        <>
            <DataTable value={result.data}>
                <Column field="name" header="Name" />
                <Column field="balance" header="Balance" />
            </DataTable>
            <p>
                Page {result.paging.page + 1} of {result.paging.totalPages}
                ({result.paging.totalItems} total items)
            </p>
            <button
                disabled={result.paging.page === 0}
                onClick={() => setPage(result.paging.page - 1)}>
                Previous
            </button>
            <button
                disabled={result.paging.page >= result.paging.totalPages - 1}
                onClick={() => setPage(result.paging.page + 1)}>
                Next
            </button>
        </>
    );
};

Return Tuple for Paged Queries

useWithPaging returns an extended tuple:

Index Name Type Description
0 result QueryResultWithState<T> Query result including paging metadata
1 perform () => Promise<void> Re-execute the query
2 setSorting (sorting: Sorting) => Promise<void> Change sort field and direction
3 setPage (page: number) => Promise<void> Navigate to a specific page (zero-based)
4 setPageSize (pageSize: number) => Promise<void> Change number of items per page

Paging Metadata

Paging information is available on result.paging:

Property Type Description
page number Current zero-based page number
size number Items per page
totalItems number Total items across all pages
totalPages number Total number of pages

Hook Variants with Paging

Hook Description
MyQuery.useWithPaging(pageSize) Standard query with paging
MyQuery.useSuspenseWithPaging(pageSize) Suspense-compatible query with paging
MyObservableQuery.useWithPaging(pageSize) Observable query with paging

Each variant accepts optional args and optional sorting.

Sorting with Paging

Sorting is independent of paging and works with all query hooks.

import { Sorting, SortDirection } from '@cratis/arc/queries';

// Initial sorting
const [result] = AllAccounts.use(undefined, new Sorting('name', SortDirection.ascending));

// Change sorting dynamically
const [paged, perform, setSorting] = AllAccounts.useWithPaging(25);
await setSorting(new Sorting('balance', SortDirection.descending));

Important Requirement

Automatic paging requires the backend to return IQueryable<T>. If the backend returns IEnumerable<T> or List<T>, paging parameters are sent but ignored, and all rows are returned in one response.

See Also