Thuta Learning
IntermediateWeb Developmentintermediate

Filtering and Pagination with Search Params

Relax. We'll talk through this in plain words — no textbook voice.

What you'll walk away with

  • Read the searchParams Promise
  • Treat the URL as UI state
  • Set input validation and default values

If you only keep a search keyword in component state, it disappears on page refresh, and you can't send a friend a link to the filtered results. Put it in the URL query string instead, and back/forward, bookmarking, and sharing all just work.

The mental model

You can await a page component's searchParams to read q and page. Since users can edit the URL by hand, convert the page number with Number and validate that it's at least 1. If you don't want to hit the server on every keystroke, debounce in a Client Component and change the URL with router.replace.

Let's build it together

tsx
export default async function NotesPage({
  searchParams,
}: {
  searchParams: Promise<{ q?: string; page?: string }>;
}) {
  const params = await searchParams;
  const query = params.q?.trim() ?? "";
  const requestedPage = Number(params.page ?? "1");
  const page = Number.isFinite(requestedPage) && requestedPage > 0
    ? requestedPage
    : 1;
  const notes = await searchNotes({ query, page });

  return <NoteList notes={notes} />;
}

How the code works

If q is missing, it defaults to an empty string; if page is invalid, it defaults to 1. The data function only accepts normalized values, so unexpected queries are handled in one place.

You should see
Opening /notes?q=next&page=2 shows the second page of results for the keyword Next.

5-Minute Try-It

Add a tutorial filter with a difficulty=beginner query, defaulting to all for an unrecognized difficulty value.

Next.js — Fetching DataNext.js

Easy traps

  • Using a string straight from the URL in a database query without validating it
  • Keeping filter state that should be shareable only in local state

Exercise

Add a tutorial filter with a difficulty=beginner query, defaulting to all for an unrecognized difficulty value.

You'll know it worked when: Opening /notes?q=next&page=2 shows the second page of results for the keyword Next.

Filtering and Pagination with Search Params | Thuta Learning