0
0
GraphqlHow-ToBeginner · 4 min read

How to Use first and after for Pagination in GraphQL

In GraphQL, use the first argument to specify how many items to fetch, and the after argument to indicate the cursor after which to start fetching. This combination enables cursor-based pagination, allowing clients to load data in chunks efficiently.
📐

Syntax

The first argument defines the number of items to return from the list. The after argument takes a cursor string that marks the position after which to start fetching items.

These arguments are typically used together in a query field that returns a Connection type, which includes edges and pageInfo for pagination details.

graphql
query GetItems($first: Int!, $after: String) {
  items(first: $first, after: $after) {
    edges {
      node {
        id
        name
      }
      cursor
    }
    pageInfo {
      endCursor
      hasNextPage
    }
  }
}
💻

Example

This example fetches the first 3 items from a list, then uses the endCursor from the response to fetch the next 3 items starting after that cursor.

graphql
query FetchFirst3Items {
  items(first: 3) {
    edges {
      node {
        id
        name
      }
      cursor
    }
    pageInfo {
      endCursor
      hasNextPage
    }
  }
}

# Suppose the response's pageInfo.endCursor is "cursor3"

query FetchNext3Items {
  items(first: 3, after: "cursor3") {
    edges {
      node {
        id
        name
      }
      cursor
    }
    pageInfo {
      endCursor
      hasNextPage
    }
  }
}
Output
{ "data": { "items": { "edges": [ {"node": {"id": "1", "name": "Item 1"}, "cursor": "cursor1"}, {"node": {"id": "2", "name": "Item 2"}, "cursor": "cursor2"}, {"node": {"id": "3", "name": "Item 3"}, "cursor": "cursor3"} ], "pageInfo": { "endCursor": "cursor3", "hasNextPage": true } } } } { "data": { "items": { "edges": [ {"node": {"id": "4", "name": "Item 4"}, "cursor": "cursor4"}, {"node": {"id": "5", "name": "Item 5"}, "cursor": "cursor5"}, {"node": {"id": "6", "name": "Item 6"}, "cursor": "cursor6"} ], "pageInfo": { "endCursor": "cursor6", "hasNextPage": false } } } }
⚠️

Common Pitfalls

  • Not using the after cursor correctly causes repeated data or missing items.
  • Using first without after always fetches from the start, ignoring pagination.
  • Assuming after is an offset number instead of a cursor string leads to errors.
  • Not checking hasNextPage can cause unnecessary requests when no more data exists.
graphql
query WrongPagination {
  items(first: 3, after: "3") {  # Incorrect: '3' is not a cursor
    edges {
      node {
        id
        name
      }
      cursor
    }
    pageInfo {
      endCursor
      hasNextPage
    }
  }
}

# Correct usage:
query CorrectPagination {
  items(first: 3, after: "cursor3") {
    edges {
      node {
        id
        name
      }
      cursor
    }
    pageInfo {
      endCursor
      hasNextPage
    }
  }
}
📊

Quick Reference

ArgumentDescriptionType
firstNumber of items to fetchInt!
afterCursor after which to start fetchingString
edgesList of items with cursorsArray
pageInfo.endCursorCursor for last item in current pageString
pageInfo.hasNextPageIndicates if more pages existBoolean

Key Takeaways

Use first to limit how many items you get in one request.
Use after with a cursor to fetch the next page of results.
Always check pageInfo.hasNextPage to know if more data is available.
The after value must be a cursor string, not a numeric offset.
Combine first and after for smooth cursor-based pagination.