javascript 53 lines · 10 steps

Parsing search params in a Next.js page

A Next.js server component sanitizes URL query params into a typed filter object before querying products.

Explained by highlit
1import { notFound } from 'next/navigation';
2 
3const PER_PAGE = 24;
4const SORT_OPTIONS = ['relevance', 'price-asc', 'price-desc', 'newest'];
5 
6function parseFilters(searchParams) {
7 const q = typeof searchParams.q === 'string' ? searchParams.q.trim() : '';
8 
9 const sort = SORT_OPTIONS.includes(searchParams.sort)
10 ? searchParams.sort
11 : 'relevance';
12 
13 const page = Math.max(1, Number.parseInt(searchParams.page, 10) || 1);
14 
15 const min = Number.parseFloat(searchParams.min);
16 const max = Number.parseFloat(searchParams.max);
17 const minPrice = Number.isFinite(min) && min >= 0 ? min : null;
18 const maxPrice = Number.isFinite(max) && max >= 0 ? max : null;
19 
20 const categories = []
21 .concat(searchParams.category ?? [])
22 .filter((c) => typeof c === 'string' && c.length > 0);
23 
24 const inStock = searchParams.inStock === 'true';
25 
26 return { q, sort, page, minPrice, maxPrice, categories, inStock };
27}
28 
29export default async function ProductsPage({ searchParams }) {
30 const filters = parseFilters(await searchParams);
31 
32 if (filters.minPrice !== null && filters.maxPrice !== null && filters.minPrice > filters.maxPrice) {
33 notFound();
34 }
35 
36 const { products, total } = await searchProducts({
37 ...filters,
38 limit: PER_PAGE,
39 offset: (filters.page - 1) * PER_PAGE,
40 });
41 
42 if (filters.page > 1 && products.length === 0) {
43 notFound();
44 }
45 
46 return (
47 <ProductGrid
48 products={products}
49 filters={filters}
50 totalPages={Math.ceil(total / PER_PAGE)}
51 />
52 );
53}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1User-supplied query params are untrusted strings, so coerce and bound each one before using it.
  2. 2Centralizing parsing in one function gives every downstream consumer a clean, predictable filter shape.
  3. 3Returning notFound() for impossible or empty states keeps invalid URLs from rendering broken pages.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Parsing search params in a Next.js page — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code