Back to Top

Use of fetchMore useQuery in nextJs

Updated 25 June 2024

As We know hooks are very useful part in Headless Development. So, Here is an implementation of using the Pagination of Apollo Client in a convenient way.

The fetchMore function of ApolloClient provides us an option to request the data with updated query parameters and to merge the results of the previous and latest responses.

About fetchMore function –

Pagination always involves sending follow-up queries to your GraphQL server to obtain additional pages of results.

In Apollo Client, the recommended way to send these follow-up queries is with the fetchMore function.
You can go through the FetchMore section of Apollo for in-depth knowledge.

Let’s start with taking an example to implement the fetchMore function. The basic idea in this example is to simply get all posts by clicking the Load More Button.

Start your headless eCommerce
now.
Find out More

Setup:

Let’s do the setup, I hope you all are aware to set up the Apollo Client, no worries if you are just beginning. Here is the official link of Apollo Client for setting up ApolloClient in nextJs.

And, for next.js project setup you can checkout our another blog: NextJs Setup

npm install @apollo/client graphql 
//To install apolloClient and graphql using the command in terminal.
//_app.js file

import "@/styles/globals.css"
import {
  ApolloProvider,
  ApolloClient,
  InMemoryCache,
  gql,
} from "@apollo/client";

export default function App({ Component, pageProps }) {
  const client = new ApolloClient({
    uri: "https://graphqlzero.almansi.me/api",
    cache: new InMemoryCache(),
  });

  client
    .query({
      query: gql`
        query Posts {
          posts {
            data {
              id
              title
              body
              user {
                name
                email
                company {
                  name
                }
                id
              }
            }
            meta {
              totalCount
            }
          }
        }
      `,
    })
    .then((result) => console.log(result));

  return (
    <ApolloProvider client={client}>
      <Component {...pageProps} />
    </ApolloProvider>
  );
}

Illustration of useQuery & fetchMore:

In the _app.js file, we did the setup of creating an instance of ApolloClient, providing our URI and query to get fetched, and in response getting the result.
Note: We have wrapped the Component inside our ApolloProvider to make the apolloClient global in the application.

FetchMore Component to fetch the graphql Query:

//FetchMore.js

import { useQuery, gql } from "@apollo/client";

export const POSTS_QUERY = gql`
  query Posts($Page: Int!, $Limit: Int!) {
    posts(options: { paginate: { page: $Page, limit: $Limit } }) {
      data {
        id
        title
        body
        user {
          name
          email
          company {
            name
          }
          id
        }
      }
      meta {
        totalCount
      }
    }
  }
`;

export default function FetchMore() {
  const offset = 1;
  const { loading, error, data, fetchMore } = useQuery(POSTS_QUERY, {
    variables: { Page: offset, Limit: 3 },
  });

  const handleLoadMore = () => {
    fetchMore({
      variables: {
        Page: offset + 1,
      },
      updateQuery: (prev, { fetchMoreResult }) => {
        if (!fetchMoreResult) return prev;
        return Object.assign({}, prev, {
          posts: {
            ...fetchMoreResult.posts,
            data: [...prev.posts.data, ...fetchMoreResult.posts.data],
          },
        });
      },
    });
  };

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error : {error.message}</p>;

  return (
    <>
      <h1
        style={{
          textAlign: "center",
          textDecoration: "underline",
          marginTop: "20px",
        }}
      >
        OUR BLOG SITE
      </h1>
      {data.posts.data.map(({ id, body, title, user }) => (
        <div style={{ padding: "20px" }} key={id}>
          <h3>
            {id}. <span style={{ textTransform: "capitalize" }}>{title}</span>
          </h3>
          <br />
          <p style={{ textAlign: "justify" }}>
            <span style={{ fontWeight: "bold" }}>Blog: </span>
            <span>{body}</span>
          </p>
          <br />
          <b>About this user:</b>
          <p>
            <b>By: </b> <span>{user.name}</span>
          </p>
          <br />
          <hr />
        </div>
      ))}
      <div style={{ alignItems: "", paddingBottom: "20px" }}>
        <center>
          <button
            style={{
              padding: "8px 10px",
              fontSize: "20px",
              backgroundColor: "green",
              color: "white",
            }}
            onClick={handleLoadMore}
          >
            <b>Click to Load More</b>
          </button>
        </center>
      </div>
    </>
  );
}
  • The FetchMore Component is responsible for first fetching the query using the useQuery Hook.
  • By destructuring the useQuery Hook, we are taking out the data, loading, error, and fetchMore props of the hook.
  • Initially, we pass the values of the variables for pageSize equal to 1 and limit 3. In this phase we get the data having 3 post items.
  • Then we created a function to load more posts at the click of a button. Here comes the role of our fetchMore function, we are passing the value of query variables again.
  • Further, we update the query response data, and in return, we get an updated response.
  • On getting a new response, we simply added/merged the previous and new responses as per need.
  • In conclusion, we are receiving the next post entries on clicks.
//pages/post.js 

import React from "react";
import FetchMore from "@/components/FetchMore";

const Post = () => {
  return (
    <div>
     <FetchMore/>
    </div>
  );
};

export default Post;

In the post.js page, we have imported the FetchMore Component to render on the browser.

Output :

Posts on clicking fetchMore

Posts fetched as per initial limit and page values passed.

Posts on clicking fetchMore

Posts fetched on click and get merged via updatedQuery, as per limit and page values passed in fetchMore Function.

Conclusion –

I hope the example will be helpful for you to understand the key concept of fetchMore and Pagination in useQuery.

In simple terms, since we need additional pages after we have fetched the initial data, pages, to achieve this we send follow-up queries using the fetchMore function of the useQuery hook.

In addition, additional examples of useFetchMore are provided in the detailed documentation for offset-based pagination and cursor-based pagination. If any doubts you can go through the blog once again.

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home