Menu
Coddy logo textTech

Filtering with the URL

Part of the Next.js Essentials section of Coddy's React journey — lesson 36 of 47.

In Fundamentals you filtered a list by keeping the chosen category in state. It worked, but the filter lived only in the browser's memory. Reload, and it's gone. Send someone the link, and they see the unfiltered list.

Put the filter in the URL instead and all of that fixes itself:

/menu?category=pizza

Everything after the ? is the query string, and a server page receives it as a prop called searchParams. Like params, it is a promise, so you await it:

export default async function MenuPage({ searchParams }) {
    const { category } = await searchParams;
    const shown = category
        ? dishes.filter((dish) => dish.category === category)
        : dishes;
    // ...
}

Read what that actually does. The filtering happens on the server, before the page is sent: the browser never receives the dishes it isn't showing. And the URL is now the state, which means it is shareable, bookmarkable, and survives a reload.

Every value in searchParams is a string (or undefined when absent). ?page=2 gives you '2', not 2.

One naming trap: the server prop searchParams resolves to a plain object you destructure. The client hook useSearchParams() is a different thing: it returns a URLSearchParams object you read with .get('category'). Same idea, two APIs, chosen by which side of the boundary you're on.

challenge icon

Challenge

Medium

Make the menu filter itself from the URL.

In app/menu/page.jsx:

  1. Read category out of searchParams (remember it's a promise).
  2. If a category was given, show only the dishes whose category matches it. If not, show all of them.

Keep rendering the names into #dish-list and the count into #dish-count. /menu?category=pizza should show 2 of the 4.

Try it yourself

import './globals.css';

export const metadata = {
    title: 'My App',
};

export default function RootLayout({ children }) {
    return (
        <html lang="en">
            <body>
                {children}
            </body>
        </html>
    );
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Next.js Essentials