Tutorial: How to implement infinite loading with URQL GraphQL
Jasser Mark Arioste
So you’re tasked with implementing an infinite loading pattern on mobile using a graphql schema. Let me share my knowledge on how to implement infinite loading on URQL on a Next.js Project. In this tutorial, I’ll be showing you on how to implement infinite loading on URQL with rick and morty api as our backend endpoint
Infinite loading a is very common pattern in mobile layout since it’s optimized for mobile UX as opposed to pagination which is more suited for desktop. There are many ways to implement infinite loading in URQL however today I’m going to show to you probably the most simple pattern to implement infinite loading pattern using a custom hook.
How does and infinite loading pattern work?
For infinite loading, we have to create a custom hook that tracks the following: the **page number **and the new items from graphql cache. Every time the page changes, we have to update the items displayed.
Step 1: Project Setup
Please see the tutorial on how to setup URQL with Next.js as we’ll continue from that tutorial. It also contains setup for the rick and morty api and the episodes list that we’ll be using so don’t skip that part! Once you finish the setup, proceed to the next step.
Step 2: Modifying the Episodes Query
Let’s modify the episodes query in episodes.graphql by adding information on the next page
#episodes.graphql
query Episodes($page: Int) {
episodes(page: $page) {
results {
air_date
created
episode
name
}
#Add this part
info {
next
}
}
}
Run yarn gen to regenerate the graphql types.
Step 3: Creating the Custom Hook
Lets create the file first:
#create the hooks folder in the root project directory for all our custom hooks
mkdir hooks && cd hooks
touch useLoadEpisodes.tsx
Insert the code:
//useLoadEpisodes.tsx
import { useEffect, useState } from "react";
import { useEpisodesQuery } from "../graphql/episodes.gql";
import { Episode } from "../graphql/types";
export const useLoadEpisodes = () => {
const [items, setItems] = useState<Partial<Episode | null>[]>([]);
const [page, setPage] = useState(1);
const [{ data, fetching }] = useEpisodesQuery({
variables: {
page: page,
},
});
const episodes = data?.episodes?.results ?? [];
//this is the important part, whenever the episodes changes, we concatenate it to the previous list
useEffect(() => {
setItems(items.concat(episodes));
}, [episodes]);
const next = data?.episodes?.info?.next;
//when load more is called, we modify the page so that it triggers another query to the backend.
const loadMore = () => {
if (next) {
setPage(next!);
}
};
//return the important items for our interface
return {
items,
hasNext: Boolean(next),
loadMore,
fetching,
};
};
Step 4: Implement infinite loading in pages/index.tsx
Inside pages/index.tsx , we’ll make a couple of changes to take into account infinite loading:
//pages/index.tsx
import type { NextPage } from "next";
import { useLoadEpisodes } from "../hooks/useLoadEpisodes";
const Home: NextPage = () => {
//use the custom hook instead of the generated hook
const { items, hasNext, loadMore, fetching } = useLoadEpisodes();
const episodes = items;
return (
<div className="container">
{/* this stays the same */}
<ol className="episode-list">
{episodes?.map((episode, i) => {
return (
<li key={i} className="episode">
<h2 className="episode-title">{episode?.name}</h2>
<p className="episode-ep">{episode?.episode}</p>
<time dateTime={episode?.air_date ?? ""}>
{episode?.air_date}
</time>
</li>
);
})}
</ol>
{/* add loading indicator for when we are fetching data from the api */}
{fetching && <p>Loading...</p>}
{/* add a load more button and call loadMore when clicked */}
{/* hide it there are no next pages */}
{!fetching && hasNext && (
<button className="load-more" onClick={loadMore}>
Load more
</button>
)}
</div>
);
};
export default Home;
Bonus Step: Style and Refactor your components
I’ll leave this step up to you since it’s out of the scope of this tutorial. However, you may check the completed code and the demo below:
Full Code: https://github.com/jmarioste/setup-urql-nextjs/tree/infinite-loading-2 Demo: https://setup-urql-nextjs-git-infinite-loading-2-jmarioste.vercel.app/
Resources
URQL Docs - https://formidable.com/open-source/urql/docs/
Credits - Photo by Rafael Cerqueira from Pexels


