State that belongs in the URL
Dynamic segments identify which thing a page shows (/blog/hello-world). But search results, filters, and page numbers are a different kind of state: how to show a listing. The web's convention for that is the query string — the part of a URL after ?, made of key=value pairs:
/search?q=shoes&page=2Putting this state in the URL instead of useState is what makes results shareable (paste the link, your teammate sees the same filtered view), bookmarkable, and back-button friendly. Every serious store, search engine, and admin table works this way, and you will build one within weeks of writing Next.js at work.
A page component receives the parsed query string as the searchParams prop — and like params in this unit, current Next.js makes it a Promise you must await:
// app/search/page.js export default async function SearchPage({ searchParams }) { const { q, page } = await searchParams; const results = await findProducts(q, Number(page ?? 1)); return <h1>{results.length} results for "{q}"</h1>; }
Two consequences to decode
- Every value is a string (or missing). The URL is text, so
pagearrives as"2", not2, and isundefinedwhen the visitor omits it. Defensive parsing with a default is not optional — users hand-edit URLs. - Reading
searchParamsmakes the page dynamic. The server cannot know?q=shoesat build time, so the page renders per request. (Unit 7 turns this into a general rule.) Dynamic segments differ here:generateStaticParamscan list slugs ahead of time, but nobody can list every possible query.
Linking into a filtered view is just a query string in href:
<Link href="/search?q=shoes&page=2">Next page</Link>Code exercise · javascript
Harden the pagination parsing (pure JavaScript, runnable here). Write pageNumber(searchParams): given an object like { page: "3" }, return the page as an integer. Default to 1 when page is missing, not a whole number, or less than 1 — users type anything into URLs.
Quiz
Why put a product list's filters in the query string (?category=lamps&sort=price) instead of a useState hook?
Problem
A page reads searchParams to show ?q= search results. At build time, can next build prerender it as static HTML, yes or no?