Home > Back-end >  How to use cursor-based pagination with Next.js API Route, Prisma and useSWRInfinite?
How to use cursor-based pagination with Next.js API Route, Prisma and useSWRInfinite?

Time:08-22

I'm trying to add cursor-based pagination to a table of posts using a Next.js API Route, Prisma and useSWRInfinite.

Currently, I'm using Prisma with a Next.js API Route to fetch the ten most recent posts for a site with useSWR, sorted by createdAt in descending order.

I'd like to use the useSWRInfinite hook to access the API endpoint and display a 'Load More' button to load a further ten posts using cursor-based pagination, in addition to displaying a count of the total number of posts.

As I understand from the SWR and Prisma docs, the API route will need to be modified to accept a cursor and return the next cursor. The useSWRInfinite hook also needs some logic to send/receive the current/next cursor.

Here is the code:

API Route

export async function getPost(
  req: NextApiRequest,
  res: NextApiResponse,
  session: Session
): Promise<void | NextApiResponse<AllPosts | (WithSitePost | null)>> {
  const { postId, siteId, published } = req.query;

  if (
    Array.isArray(postId) ||
    Array.isArray(siteId) ||
    Array.isArray(published)
  )
    return res.status(400).end("Bad request. Query parameters are not valid.");

  if (!session.user.id)
    return res.status(500).end("Server failed to get session user ID");

  try {
    if (postId) {
      const post = await prisma.post.findFirst({
        ...
      });

      return res.status(200).json(post);
    }

    const site = await prisma.site.findFirst({
      where: {
        id: siteId,
        user: {
          id: session.user.id,
        },
      },
    });

    const posts = !site
      ? []
      : await prisma.post.findMany({
          take: 10,
          where: {
            site: {
              id: siteId,
            },
            published: JSON.parse(published || "true"),
          },
          orderBy: {
            createdAt: "desc",
          },
        });

    return res.status(200).json({
      posts,
      site,
    });
  } catch (error) {
    console.error(error);
    return res.status(500).end(error);
  }
}

Posts Page

const router = useRouter();
const { id: siteId } = router.query;

const { data } = useSWR<SitePostData>(
    siteId && `/api/post?siteId=${siteId}&published=true`,
    fetcher,
    {
        onSuccess: (data) => !data?.site && router.push("/"),
    }
);

CodePudding user response:

Take a look at Prisma's documentation on cursor-based pagination: https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination

You can provide a skip property to skip X elements in your findMany query, and/or a cursor property to tell Prisma where to start the find from. You will need both: skip: 1 to skip the cursor, and cursor to indicate the ID of the property from which the find should begin.

  • Related