Andy Richardson
Posted on April 28, 2021
Note: This is a multi-part series; if you already know about relay pagination, feel free to skip to the next section.
Relay's Cursor Connection Specification has become the industry standard for pagination in GraphQL.
Whether you use a Relay, Apollo, or urql, the spec is supported by many client side libraries. This makes it an easy choice for those who don't want to implement their own client-side pagination logic (which is most of us).
π¬ Pagination grammar
Before we declare a pageable field, you're going to want to know about the following primitives.
Edge
An Edge is a container type which ensures that each item in a paginated response (node) is accompanied with a position in the collection (cursor).
type UserEdge {
node: User!
cursor: String!
}
PageInfo
PageInfo is a metadata type which provides information about a pagination request.
type PageInfo {
startCursor: String
endCursor: String
hasNextPage: Boolean!
hasPreviousPage: Boolean!
}
Connection
A Connection is a container type which aggregates Edge and PageInfo values and is the root type of any paginated response.
type UserConnection {
edges: [UserEdge!]!
pageInfo: PageInfo!
}
π¨ Creating a pageable field
Adding pagination support to a field is pretty straightforward. The field needs to take the following four arguments - first
, after
, last
, and before
(more on this later) - and return a Connection.
type Query {
users(
first: Int,
after: String,
last: Int,
before: String
): UserConnection!
}
ποΈ Page traversal
Paginated fields take four arguments which can be divided into two distinct groups.
Forward pagination
Forward pagination is the process of fetching pages in a collection from top-to-bottom.
Arguments
The arguments to use forward pagination are:
-
first
- the number of items to return (required) -
after
- a cursor resembling the position in the collection to start from (optional)
Retrieval
As you can see above, the first paginated query will include only the first
argument. This tells the backend to start at the top of the collection.
For subsequent queries the after
argument is used to instruct the backend where to continue from. This value corresponds to the cursor of the last edge on the previous response.
Backward pagination
Backward pagination is the process of fetching pages in a collection from bottom-to-top.
Arguments
The arguments to use backward pagination are:
-
last
- the number of items to return (required) -
before
- a cursor resembling the position in the collection to start from (optional)
Retrieval
This second example might look familiar - that's because it's almost identical to forward pagination.
Just like with forward pagination, the page size is sent in isolation for the first query (this time last
rather than first
).
Again, for subsequent queries, a cursor is provided to instruct the backend where to continue from (this time before
rather than after
). This value corresponds to the cursor on the first (as opposed to last) edge on the previous response.
It's important to note, the sort order in which edges are returned is the same regardless of whether forward or backward pagination is used.
Thanks for reading!
If you enjoyed this post, be sure to react π¦ or drop a comment below with any thoughts π€.
You can also hit me up on twitterβ-β@andyrichardsonn
Disclaimer: All thoughts and opinions expressed in this article are my own.
Posted on April 28, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.