Reading list Switch to dark mode

    Use of fetchMore useQuery in nextJs

    Updated 31 May 2023

    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.

    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.

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

    Illustration of useQuery & fetchMore:

    //_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>
      );
    }

    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.

    Start your headless eCommerce
    now.
    Find out More

    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 use fetchMore 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