PageInfo Type
The PageInfo type provides pagination information for list queries.
Type Definition
"""
Information about pagination in a connection.
"""
type PageInfo {
"""
Indicates if there are more pages after the current one.
"""
hasNextPage: Boolean!
"""
Indicates if there are previous pages before the current one.
"""
hasPreviousPage: Boolean!
"""
Cursor to use for getting the next page.
"""
endCursor: String
"""
Cursor to use for getting the previous page.
"""
startCursor: String
}
Fields
| Field | Type | Description |
|---|---|---|
hasNextPage | Boolean! | Required. Whether there are more items |
hasPreviousPage | Boolean! | Required. Whether there are previous items |
endCursor | String | Optional. Cursor for next page |
startCursor | String | Optional. Cursor for previous page |
Usage
In List Queries
query GetLocationHistory {
locationHistory(trackerId: "tracker_123", first: 10, after: "cursor_xyz") {
nodes {
id
timestamp
}
pageInfo {
hasNextPage
endCursor
hasPreviousPage
startCursor
}
totalCount
}
}
Forward Pagination
query GetNextPage {
trackers(first: 10, after: "cursor_xyz") {
nodes {
id
status
}
pageInfo {
hasNextPage
endCursor
}
}
}
Backward Pagination
query GetPreviousPage {
trackers(last: 10, before: "cursor_xyz") {
nodes {
id
status
}
pageInfo {
hasPreviousPage
startCursor
}
}
}
Pagination Patterns
Connection Pattern
"""
A connection pattern for paginated lists.
"""
type TrackerConnection {
"""
List of tracker nodes.
"""
nodes: [Tracker!]!
"""
Pagination information.
"""
pageInfo: PageInfo!
"""
Total count of items available.
"""
totalCount: Int!
}
Cursor-based Navigation
type Query {
"""
Get a paginated list of trackers.
"""
trackers(
"""
Number of items to fetch going forward.
"""
first: Int
"""
Number of items to fetch going backward.
"""
last: Int
"""
Cursor to fetch items after.
"""
after: String
"""
Cursor to fetch items before.
"""
before: String
): TrackerConnection!
}
Best Practices
-
Cursor Handling
- Use opaque cursors
- Base64 encode cursor data
- Include sorting information
-
Page Sizes
- Set reasonable defaults
- Enforce maximum limits
- Document limitations
-
Performance
- Use efficient cursor encoding
- Optimize cursor queries
- Cache common pages
-
Error Handling
- Validate cursor format
- Handle invalid cursors
- Provide clear error messages
Implementation Example
interface PaginationArgs {
first?: number;
last?: number;
after?: string;
before?: string;
}
interface Connection<T> {
nodes: T[];
pageInfo: PageInfo;
totalCount: number;
}
async function createConnection<T>(
args: PaginationArgs,
fetchFn: (args: PaginationArgs) => Promise<T[]>,
countFn: () => Promise<number>,
): Promise<Connection<T>> {
const limit = args.first || args.last || 10;
const nodes = await fetchFn(args);
const totalCount = await countFn();
return {
nodes,
pageInfo: {
hasNextPage: nodes.length === limit,
hasPreviousPage: !!args.after || !!args.before,
startCursor: nodes[0]?.id,
endCursor: nodes[nodes.length - 1]?.id,
},
totalCount,
};
}