Pagination

We use a relay-style cursor based pagination for every potentially unlimited list.

Every paginated entity follow the same logic. To navigate between pages, we use an input paginationInput in which we have a size and a where clause. The size is the number of items you want. The where is another input that contains a cursor which is basically the id of the item we will start from and the direction which is a simple enum.

input PaginationInput {
  size: Int
  where: PagintationWhereInput
}

input PagintationWhereInput {
  cursor: String!
  direction: PagintationWhereDirectionInput!
}

enum PagintationWhereDirectionInput {
  BEFORE
  AFTER
}

When fetching a list of paginated entities, the return type will always implement the Connection interface which follows best practices of a graphql pagination. This interface is made of edges and pageInfo. Edges is another interface implemented by our paginated entities to make sure they all return a cursor from which we can continue browsing the pages. PageInfo gives more information about the edges and the page itself and is typically used for infinite scroll use cases.

interface Edge {
  cursor: String!
}

interface Connection {
  pageInfo: PageInfo!
  edges: [Edge!]!
}

type PageInfo {
  hasPreviousPage: Boolean!
  hasNextPage: Boolean!
  startCursor: String
  endCursor: String
}

Enough with the theory, let's try a simple example!

With the searchDoc query, we will browse the last created docs from our Cycle workspace.

query searchDoc {
  searchDoc(
    productId: "<productId>"
    text: ""
    pagination: { size: 5 }
  ) {
    edges {
      cursor
      node {
        id
        title
      }
    }
    pageInfo {
      hasPreviousPage
      hasNextPage
      startCursor
      endCursor
    }
  }
}

Since we are fetching the first page, hasPreviousPage should be false and hasNextPage should be true. startCursor should match the cursor of our first element and endCursor, obviously, the last one. Let's use endCursor to fetch the nextPage.

query searchDoc {
  searchDoc(
    productId: "<productId>"
    text: ""
    pagination: {
      size: 5
      where: {
        cursor: "<endCursor>"
        direction: AFTER # since we want the elements after the endCursor. Use BEFORE if you want to go the other way.
      }
    }
  ) {
    edges {
      cursor
      node {
        id
        title
        createdAt
      }
    }
    pageInfo {
      hasPreviousPage
      hasNextPage
      startCursor
      endCursor
    }
  }
}

Let's take a deep breath maybe some coffee ☕️ before diving into the possible automations thanks to our webhooks. If you think you've already learned enough, you can jump to the Create a feedback section to develop your first real life use case.

Last updated