GraphQL Cursor Base Pagination With Apollo

Fatemeh Paghar - Dec 15 '22 - - Dev Community

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .