DEV Community

Fatemeh Paghar
Fatemeh Paghar

Posted on • Edited on

GraphQL Cursor Base Pagination With Apollo

GraphQL allows us to retrieve exactly the fields we need from the data graph, it allows us to query the fields we need. While most of the time this gives us the short answer we want, in some cases the data graph contains a lot of data, and the query returns much more data than we need.

With GraphQL, there is now an option to paginate query results and limit them to specific sections. There are two methods of getting paged data: numbered pages and cursors. There are also two ways of displaying paged data: discrete pages and infinite scrolling.

In the example below, we use Apollo to implement cursor pagination with infinite scrolling approaches with GraphQL API.

import React from "react";
import {useQuery,gql,ApolloProvider} from "@apollo/client";
import {ApolloClient,InMemoryCache} from "@apollo/client";

const client = new ApolloClient({
    cache: new InMemoryCache(),
    uri: "https://api.github.com/graphql",
    headers: {        
        "Authorization"`bearer {process.env.REACT_APP_GITHUB_KEY}`           
    }
});

const REPOS_QUERY = gql`
  query repoQuery($after: String,$before:String) {
    repository(owner: "reactjs", name: "reactjs.org") {
    issues(first: 30,before: $before,after: $after) {
      edges {
        node {
          title
          url
          state
        }
      }
      pageInfo {
        endCursor
        hasNextPage
        hasPreviousPage
        startCursor
      }
    }
  }   
}`;

function Issues() {  
  const { data, error, loading, fetchMore } = useQuery(REPOS_QUERY);
  if (error) return <div>errors</div>;
  if (loading || !data) return <div>loading</div>;

  return (
    <>
      <ul>
        {data.repository.issues.edges.map(({ node }) => (
          <li key={node.id}>{node.title}</li>
        ))}
      </ul>

      <button
        onClick={() => {
          const { endCursor } = data.repository.issues.pageInfo;

          fetchMore({
            variables: { after: endCursor },
            updateQuery: (prevResult, { fetchMoreResult }) => {
              fetchMoreResult.repository.issues.edges = [
                ...prevResult.repository.issues.edges,
                ...fetchMoreResult.repository.issues.edges
              ];
              return fetchMoreResult;
            }
          });

        }}
      >
        more
      </button>

    </>
  );
}

function App() {
  return (
    <ApolloProvider client={client}>
      <Issues />
    </ApolloProvider>
  );
}


export default App;

Enter fullscreen mode Exit fullscreen mode

Using fetchMore

The simplest way to paginate in Apollo is to use the fetchMore function, that is contained in the result object returned by the useQuery hook. This essentially lets you run a new GraphQL query and merge the results with the previous one.

You can define which query and variables to use for the new query, in addition to how to merge the new query result with the client's existing data. The exact method you use would determine the type of pagination you use.
Source code

Top comments (6)

Collapse
 
coderincode profile image
Coder

The cursor example was perfect, just I add a definition of Offset-base pagination.
Offset-based pagination, also recognized as numbered pages, is a very common pattern found on many websites because it is usually the easiest to implement on the backend. In SQL, for example, numbered pages can be easily generated by using OFFSET and LIMIT.

Collapse
 
reazmohammadi profile image
reaz-mohammadi

tanks perfect

Collapse
 
arc91m profile image
Mahsa Ashrafi

Useful

Collapse
 
masi_78 profile image
Masoomeh

Useful

Collapse
 
negindrfsh profile image
Negin

Perfect

Collapse
 
saharb86 profile image
saharb

useful again๐Ÿ™๐Ÿป