How to Fetch Data Based on `searchParams` in Next.js

Read searchParams as a promise in a Server Component to drive filters, sorting, and pagination with server-side fetching.

7 min read

To fetch data based on searchParams in Next.js, await the promise the page receives and pass its values into your server-side request. In the App Router, searchParams resolves to the query string values of the current URL.

Because a Server Component page can be async, the whole flow stays on the server.

App.tsxApp.tsx
// app/shop/page.tsx
export default async function Page(props: PageProps<"/shop">) {
  const { query = "", sort = "asc" } = await props.searchParams;
  const params = new URLSearchParams({ q: String(query), sort: String(sort) });
  const res = await fetch(`https://api.example.com/products?${params}`);
  const products = await res.json();
  return <ul>{products.map((p) => <li key={p.id}>{p.name}</li>)}</ul>;
}

Visiting the shop route with a query string such as /shop?query=shoes&sort=desc fetches products already filtered and sorted. PageProps is the generated helper that types both params and searchParams from the route path, and URLSearchParams encodes the values so a search term with a space or an ampersand cannot break the upstream URL.

Why searchParams opts the page into dynamic rendering

searchParams is a request-time API: its values are not known until the request arrives. Reading it opts the page into dynamic rendering, so the server fetches fresh data for each request instead of reusing a prerendered page.

Without Cache Components, that applies to the whole route: it is no longer prerendered, so read searchParams only when the query genuinely drives the content.

With Cache Components enabled in Next.js 16, the position of the read is what matters. Read searchParams inside a component wrapped in Suspense and the rest of the page still prerenders as a static shell, while that section streams in at request time. For the rendering implications, see static vs dynamic rendering.

Reading searchParams in a Client Component

A client page cannot be async, so it unwraps the promise with React's use function instead of await.

App.tsxApp.tsx
// app/shop/page.tsx
"use client";
import { use } from "react";
 
export default function Page(props: PageProps<"/shop">) {
  const { query = "" } = use(props.searchParams);
  return <p>Search: {query}</p>;
}

The use function lets a client page read the promise without becoming async. The page still receives the value from the server, not from a second fetch. When client-side navigation changes the query string, the page re-renders with the new value.

Values are strings, not URLSearchParams

searchParams resolves to a plain object whose values are strings or arrays of strings. A repeated key such as ?tag=a&tag=b becomes an array, so the same code path must handle both a string and an array. The documented type is a record of string, string array, or undefined, which is why the first example wraps each value in String before building the query.

Defaults and missing keys

Use destructuring defaults to fill missing keys, as the example above does with query and sort. A missing query string key simply resolves to undefined, so defaults keep the fetch URL stable and prevent a request with an undefined segment.

Only pages receive searchParams

Only the page receives searchParams. A layout does not get it, because a shared layout does not re-render on every query string change and stale values would linger there.

Fetch the data in the page, then pass the result to any client component as props. Keeping the parse on the server also means one source of truth for the query values, instead of the client reading the URL again. For the difference between searchParams and the path-based params prop, see params vs searchParams.

Rune AI

Rune AI

Key Insights

  • searchParams is a promise in current Next.js and must be awaited.
  • Its values are strings or arrays of strings, not URLSearchParams.
  • Reading it opts the page into dynamic rendering.
  • Server Components await it; Client Components use the use function.
  • Feed the parsed values straight into a server-side fetch.
RunePowered by Rune AI

Frequently Asked Questions

Is searchParams a URLSearchParams object?

No. It resolves to a plain object whose values are strings or arrays of strings.

Does reading searchParams affect rendering?

Yes. It is a request-time API, so reading it opts the page into dynamic rendering. With Cache Components enabled, where you read it decides how much of the page still prerenders.

Can a Client Component read searchParams?

Yes, with React's use function, since a client page cannot be async.

Conclusion

searchParams resolves to the query string of the current URL as a promise. Await it in a Server Component, or unwrap it with use in a client page, and pass the values into your server-side fetch.