šŸŽ Checkout my Learn React by Making a Game course and get 1 month Free on Skillshare!

Make an infinite scroll in NextJs 13 with useInfiniteQuery()

We previously looked at how we can add pagination to NextJs 13 data fetching.

Today, let's see how to use a similar approach to build an infinite scrolling component in NextJs with useInfiniteQuery().

Something like the component below:
Make an infinite scroll in NextJs 13 with useInfiniteQuery()

If you want to skip ahead you can see the running example here and the full code on GitHub.

Fetching the first page with useInfiniteQuery

We will use the useInfiniteQuery() hook to fetch some data from the JsonPlaceholder API.

First, we will need to install the package:

npm i --save @tanstack/react-query

Given that we will use client hooks in our NextJs page, be sure to add the use client directive at the beginning of the file.

Next, we will create a new QueryClient and define a fetchData() function to get the initial data:

'use client'

import { useInfiniteQuery, QueryClient, QueryClientProvider } from "@tanstack/react-query"

const queryClient = new QueryClient();

const fetchData = async (page) => {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5&_page=' + page)
  return await response.json();
}

const MyComponent = ()=> {
  const {data, fetchNextPage, isFetchingNextPage} = useInfiniteQuery(
    ['query'], 
    async ({pageParam = 1}) => await fetchData(pageParam), 
    {
      getNextPageParam: (_, pages) => pages.length + 1
    }
  )

  return(<>
    <h1>šŸ“– Post list</h1>
    <div className="container">
      <ol>
        {data?.pages.map((page, i)=> (
          <span key={i}>
            {page.map(
              (p,i) => <li key={p.id}>{p.title}</li>
            )}
          </span>
        ))}
      </ol>
    </div>
  </>)
}

export default function Home() {
  return (
    <QueryClientProvider client={queryClient}>
        <MyComponent />
    </QueryClientProvider>
  )
}

At this point, we will only fetch the first page of data:
Make an infinite scroll in NextJs 13 with useInfiniteQuery()

Let's next see how we can expand this to become an infinite scrolling component.

Adding infinite scrolling

You may have noticed that one of the things the useInfiniteQuery() returns is the fetchNextPage function.

In the initial pagination example, we had a load more button that was triggering the fetchNextPage call.

We can tweak that example so that we get the infinite scrolling effect by doing the following:

  1. add an invisible element <span ref={myRef}></span> at the end of the list
  2. use an IntersectionObserver to listen for when the myRef() element comes into view and make the fetchNextPage() call.
    Make an infinite scroll in NextJs 13 with useInfiniteQuery()

And below is the full code that will accomplish the infinite scrolling effect in NextJs:

'use client'

import { useInfiniteQuery, QueryClient, QueryClientProvider } from "@tanstack/react-query"
import { useRef, useEffect } from "react"

const fetchData = async (page) => {
  const response = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5&_page=' + page)
  return await response.json();
}

const queryClient = new QueryClient();

const MyComponent = ()=> {
  const myRef = useRef(null)

  const {data, fetchNextPage, isFetchingNextPage} = useInfiniteQuery(
    ['query'], 
    async ({pageParam = 1}) => await fetchData(pageParam), 
    {
      getNextPageParam: (_, pages) => pages.length + 1
    }
  )

  useEffect(()=> {
    const observer = new IntersectionObserver( 
      (entries) => {entries.forEach( e => fetchNextPage())
    })
    if (myRef.current) {
      observer.observe(myRef.current)
    }
  }, [myRef])

  return <>
    <h1>šŸ“– Post list</h1>
    <div className="container">
      <ol>
        {data?.pages.map((page, i)=> (
          <span key={i}>
            {page.map(
              (p,i) => <li key={p.id}>{p.title}</li>
            )}
          </span>
        ))}
        <span ref={myRef}></span>
      </ol>
    </div>
  </>
}

export default function Home() {
  return (
    <QueryClientProvider client={queryClient}>
        <MyComponent />
    </QueryClientProvider>
  )
}

I've put together a repo for this example and you can check out the live version on GitHub pages.

šŸ“– 50 Javascript, React and NextJs Projects

Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.

šŸ“– 50 Javascript, React and NextJs Projects

Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.


Leave a Reply

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