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.
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
, andfetchMore
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 fetched as per initial limit and page values passed.
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.
Be the first to comment.