Paginate Your Results

GraphQL queries can return up to 2000 records. By default, the wire adapter returns the first 10 results and you can request subsequent pages using the cursor information. The GraphQL API and graphql wire adapter use the GraphQL Cursor Connections Specification for pagination of all data collections they return.

Query with Cursor Information

To specify the number of records to return, use the first argument. The default number is 10. If hasNextPage is true, you can provide the endCursor value to the after argument of a subsequent query, which requests the next page of results.

note: Backward pagination using last and before isn’t currently supported.

Here’s a basic query with cursor information.

query AccountRecords {
  uiapi {
    query {
      Account (first: 5, after: "endCursorFromPreviousQuery") {
        edges {
          node {
            Id
            Name {
              value
            }
          }
        }
        totalCount
        pageInfo {
          endCursor
          hasNextPage
        }
      }
    }
  }
}

This example response contains cursor information.

{
  "data": {
    "uiapi": {
      "query": {
        "Account": {
          "edges": [
            {
              "node": {
                "Id": "001RM000005ZclBYAS",
                "Name": {
                  "value": "GenePoint"
                }
              }
            },
            {
              "node": {
                "Id": "001RM000005Zcl6YAC",
                "Name": {
                  "value": "United Oil"
                }
              }
            }
          ], // 3 more node objects here removed for brevity
          "totalCount": 5,
          "pageInfo": {
            "endCursor": "djE6Nw==",
            "hasNextPage": true
          }
        }
      }
    }
  },
  "errors": []
}

tip: Requesting totalCount can have performance implications for large or complex queries.

Implement Pagination in LWC

In this example, we create a simplePagination component with a reset button and a next page button. The reset button resets the pagination. The next page button pages through the results. The component displays 5 results on each page by default. It uses an isLastPage property to determine if the next page button is disabled.

tip: The graphqlPagination component in the lwc-recipes repo gets contact data with pagination to navigate through the list.

// simplePagination.js
import { LightningElement, wire } from "lwc";
import { gql, graphql } from "lightning/graphql";

const pageSize = 3;

export default class GraphqlPagination extends LightningElement {
  after;
  pageNumber = 1;

  @wire(graphql, {
    query: gql`
      query paginatedContacts($after: String, $pageSize: Int!) {
        uiapi {
          query {
            Contact(first: $pageSize, after: $after, orderBy: { Name: { order: ASC } }) {
              edges {
                node {
                  Id
                  Name {
                    value
                  }
                }
              }
              pageInfo {
                endCursor
                hasNextPage
                hasPreviousPage
              }
            }
          }
        }
      }
    `,
    variables: "$variables",
  })
  contacts;

  get variables() {
    return {
      after: this.after || null,
      pageSize,
    };
  }

  get isFirstPage() {
    return !this.contacts.data?.uiapi.query.Contact.pageInfo.hasPreviousPage;
  }

  get isLastPage() {
    return !this.contacts.data?.uiapi.query.Contact.pageInfo.hasNextPage;
  }

  handleNext() {
    if (this.contacts.data?.uiapi.query.Contact.pageInfo.hasNextPage) {
      this.after = this.contacts.data.uiapi.query.Contact.pageInfo.endCursor;
      this.pageNumber++;
    }
  }

  handleReset() {
    this.after = null;
    this.pageNumber = 1;
  }
}

The component uses the lightning-button base component to display the reset button and next page button. It displays the account name and annual revenue in the lightning-card base component.

<!-- prettier-ignore -->
<!-- simplePagination.html -->
<template>
  <lightning-card title="GraphqlPagination" icon-name="custom:custom39">
    <div class="slds-var-m-around_medium">
      <template lwc:if={contacts.data}>
        <template for:each={contacts.data.uiapi.query.Contact.edges} for:item="contact">
          <p key={contact.node.Id}>{contact.node.Name.value}</p>
        </template>
        <div class="slds-grid slds-grid_vertical-align-center slds-var-m-horizontal_x-small">
          <div class="slds-col slds-size_1-of-2">
            <lightning-button-icon
              disabled={isFirstPage}
              class="reset"
              icon-name="utility:skip_back"
              onclick={handleReset}
              ><label>Restart</label></lightning-button-icon
            >
          </div>
          <div class="slds-col slds-size_1-of-2">
            <lightning-button-icon
              disabled={isLastPage}
              class="next"
              icon-name="utility:chevronright"
              onclick={handleNext}
              ><label>Next</label></lightning-button-icon
            >
          </div>
        </div>
      </template>
      <template lwc:elseif={contacts.errors}>
        <c-error-panel errors={contacts.errors}></c-error-panel>
      </template>
    </div>

    <c-view-source source="lwc/graphqlPagination" slot="footer">
      Run a GraphQL query that uses pagination using @wire.
    </c-view-source>
  </lightning-card>
</template>

When clicked, the next page button sets the lastCursor value to the endCursor value and displays the next set of results.

See Also

Paginate Results

Feature Limitations of Offline GraphQL