Paging
Arc supports server-side paging for query proxies when the backend query returns IQueryable<T>.
How Paging Works
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “Sorting with Paging”Sorting is independent of paging and works with all query hooks.
import { Sorting, SortDirection } from '@cratis/arc/queries';
// Initial sortingconst [result] = AllAccounts.use(undefined, new Sorting('name', SortDirection.ascending));
// Change sorting dynamicallyconst [paged, perform, setSorting] = AllAccounts.useWithPaging(25);await setSorting(new Sorting('balance', SortDirection.descending));Important Requirement
Section titled “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.