Course

Pagination: Part Two

Let's continue our exploration of pagination in Prisma. In this lesson, we'll look at how to implement a simple pagination component to the bottom of our search results.

Pagination Component

Our pagination component will have a previous button, and a next button.

It will be a client component that uses to get the current page number, and then uses the hook to navigate to the next or previous page.

Let's make a file called in the directory.

Pagination.tsx
"use client";

import { useRouter } from "next/navigation";
import { useSearchParams } from "next/navigation";

// import our modifySearchParams helper utility
import { modifySearchParams } from "@/lib/utils";

export default function Pagination() {
  const searchParams = useSearchParams();
  const router = useRouter();
  const handlePageChange = (newPage: number) => {
   // todo: navigate to the correct page
  };

  return (
    <div className="flex justify-center gap-4">
      <button
        className="text-black disabled:text-gray-400"
      >
        Previous Page
      </button>
      <button
        className="text-black"
      >
        Next Page
      </button>
    </div>
  );
}

First let's convert our to an object we

//
const searchParams = Object.fromEntries(useSearchParams()) as any;

Next we'll need our current page. We'll default to 1 if the page is not set. We'll use this to determine if the previous button should be disabled, and which page to navigate to when the next button is clicked.

//
  const page = parseInt(searchParams.page) || 1;

Now we can implement the function. This function will navigate to the next or previous page when the buttons are clicked.

//
  const handlePageChange = (newPage: number) => {
    const query = modifySearchParams(searchParams, {
      ...searchParams,
      page: newPage,
    });
    router.push(`/search?${query}`);
  };

Our function uses the utility to update the page number in the search params. It then uses the function to navigate to the new search results page.

Insight

The utility is a helper function that takes an object of search params and a new object of search params, and returns a string of query parameters. It merges the two objects together, overwriting any existing keys with the new values.

You can find the utility in the file.

Finally, we can update the handlers for the previous and next buttons to call the function with the correct page number.

//
"use client";

import { useRouter } from "next/navigation";
import { useSearchParams } from "next/navigation";

import { modifySearchParams } from "@/lib/utils";

export default function Pagination() {
  const searchParams = Object.fromEntries(useSearchParams()) as any;

  const router = useRouter();
  const page = parseInt(searchParams.page) || 1;

  const handlePageChange = (newPage: number) => {
    const query = modifySearchParams(searchParams, {
      ...searchParams,
      page: newPage,
    });
    router.push(`/search?${query}`);
  };

  return (
    <div className="flex justify-center gap-4">
      <button
        onClick={() => handlePageChange(page - 1)}
        disabled={page === 1}
        className="text-black disabled:text-gray-400"
      >
        Previous Page
      </button>
      <button
        onClick={() => handlePageChange(page + 1)}
        className="text-black disabled:text-gray-400"
      >
        Next Page
      </button>
    </div>
  );
}

Now we have a simple pagination component that allows users to navigate between pages of search results.

Let's add it to the bottom of our search filters in the search page.

page.tsx

import ProductResult from "@/components/search/ProductResult";
import SearchFilters from "@/components/search/SearchFilters";
import { getProducts } from "@/lib/actions/products";
import Pagination from "@/components/search/Pagination";

export default async function Component({
  searchParams,
}: {
  searchParams: {
    name: string;
    category: string;
    minRating: string;
    page: string;
  };
}) {
  const page = parseInt(searchParams.page) || 1;
  const products = await getProducts({ page });

  return (
    <div className="grid md:grid-cols-[300px_1fr] gap-8 px-4 md:px-8 py-20">
      <div className="bg-white rounded-lg shadow-sm dark:bg-gray-950 p-6 space-y-6">
        <SearchFilters />
        <Pagination />
      </div>
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
        {products.map((product) => (
          <ProductResult key={product.id} product={product} />
        ))}
      </div>
    </div>
  );
}

Conclusion

In this lesson, we implemented a simple pagination component that allows users to navigate between pages of search results. We used the and hooks to get and update the page number in the search params.

0 Comments

"Please login to view comments"

glass-bbok

Join the Conversation!

Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.

Upgrade your account
tick-guideNext Lesson

Filtering