How to Implement Infinite Scroll with GraphQL Efficiently
To implement infinite scroll with
GraphQL, use cursor-based pagination by requesting a limited number of items with first and a after cursor. Fetch more data by passing the last item's cursor to after as the user scrolls, enabling smooth incremental loading.Syntax
Infinite scroll in GraphQL typically uses cursor-based pagination with these parts:
first: Number of items to fetch.after: Cursor pointing to the last fetched item.edges: List of items with cursors.pageInfo: ContainshasNextPageandendCursorto control loading.
graphql
query GetItems($first: Int!, $after: String) {
items(first: $first, after: $after) {
edges {
node {
id
name
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
}
}Example
This example shows a GraphQL query fetching 5 items at a time using cursor-based pagination. The client uses endCursor to load the next batch when scrolling.
graphql
query FetchProducts($first: Int!, $after: String) {
products(first: $first, after: $after) {
edges {
node {
id
title
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
}
}
# Variables for first fetch
{
"first": 5,
"after": null
}
# Variables for next fetch after scrolling
{
"first": 5,
"after": "cursor-from-last-item"
}Output
{
"data": {
"products": {
"edges": [
{"node": {"id": "1", "title": "Product 1"}, "cursor": "cursor1"},
{"node": {"id": "2", "title": "Product 2"}, "cursor": "cursor2"},
{"node": {"id": "3", "title": "Product 3"}, "cursor": "cursor3"},
{"node": {"id": "4", "title": "Product 4"}, "cursor": "cursor4"},
{"node": {"id": "5", "title": "Product 5"}, "cursor": "cursor5"}
],
"pageInfo": {
"hasNextPage": true,
"endCursor": "cursor5"
}
}
}
}
Common Pitfalls
Common mistakes when implementing infinite scroll with GraphQL include:
- Using offset-based pagination instead of cursor-based, which can cause duplicates or missing items when data changes.
- Not checking
hasNextPagebefore fetching more data, leading to unnecessary requests. - Failing to update the
aftercursor with the latestendCursor, causing repeated data.
graphql
query WrongPagination {
items(offset: 0, limit: 5) {
id
name
}
}
# Correct approach uses cursor-based pagination:
query CorrectPagination($first: Int!, $after: String) {
items(first: $first, after: $after) {
edges {
node {
id
name
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
}
}Quick Reference
| Term | Description |
|---|---|
| first | Number of items to fetch per request |
| after | Cursor to start fetching after |
| edges | List of items with their cursors |
| node | The actual item data |
| pageInfo | Pagination info including hasNextPage and endCursor |
| hasNextPage | Boolean indicating if more items exist |
| endCursor | Cursor of the last item fetched |
Key Takeaways
Use cursor-based pagination with first and after for reliable infinite scroll.
Always check hasNextPage before loading more data to avoid extra requests.
Update the after cursor with endCursor from the last fetch to get new items.
Avoid offset-based pagination as it can cause data inconsistencies during scrolling.
Structure your query to return edges and pageInfo for smooth incremental loading.