Pagination
Revisium uses cursor-based (Relay-style) forward pagination with first and after parameters.
Basic Pagination
query GetProducts($first: Int!, $after: String) {
products(data: { first: $first, after: $after }) {
edges {
node {
id
data { name price }
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
totalCount
}
}
First page: { "first": 20, "after": null }
Next page: { "first": 20, "after": "eyJpZCI6InByb2R1Y3QtMTIzIn0=" }
Use pageInfo.endCursor as the after value for the next page. Stop when hasNextPage is false.
With Filtering and Sorting
Pagination works with all filtering and sorting options:
query GetAvailableProducts($after: String) {
products(data: {
first: 20,
after: $after,
where: {
data: { path: ["inStock"], equals: true }
},
orderBy: [{ field: createdAt, direction: desc }]
}) {
edges {
node { data { name price } }
cursor
}
pageInfo { hasNextPage endCursor }
totalCount
}
}
Implementation Example
- React
- JavaScript
import { useState } from 'react';
import { useQuery, gql } from '@apollo/client';
const GET_PRODUCTS = gql`
query GetProducts($first: Int!, $after: String) {
products(data: { first: $first, after: $after }) {
edges {
node { id data { name price } }
}
pageInfo { hasNextPage endCursor }
totalCount
}
}
`;
function ProductsList() {
const { data, loading, fetchMore } = useQuery(GET_PRODUCTS, {
variables: { first: 20, after: null },
});
const loadMore = () => {
if (data?.products?.pageInfo?.hasNextPage) {
fetchMore({
variables: { after: data.products.pageInfo.endCursor },
});
}
};
return (
<div>
{data?.products?.edges?.map(({ node }) => (
<div key={node.id}>{node.data.name} — ${node.data.price}</div>
))}
{data?.products?.pageInfo?.hasNextPage && (
<button onClick={loadMore} disabled={loading}>Load More</button>
)}
</div>
);
}
async function fetchAllProducts(client, pageSize = 20) {
let allProducts = [];
let cursor = null;
let hasMore = true;
while (hasMore) {
const { data } = await client.query({
query: GET_PRODUCTS,
variables: { first: pageSize, after: cursor },
});
allProducts.push(...data.products.edges.map(e => e.node));
hasMore = data.products.pageInfo.hasNextPage;
cursor = data.products.pageInfo.endCursor;
}
return allProducts;
}
Best Practices
- Page size: 10-20 for mobile, 20-50 for desktop, max 500
- Stable sorting: The platform includes a default sort to ensure consistent pagination. You can add your own
orderByon top. - Field selection: Only request fields you need to reduce payload size