Suspense for search params
Wrap useSearchParams in Suspense, and dynamic usePathname.
From next-best-practices, suspense-boundaries.md.
What arrives in the HTML
Press Load page, then change JS timing or tick JS fails.
No boundaryBad
In
<Suspense>Good// app/search/page.tsx (Server Component)
import { Suspense } from 'react'
import SearchBar from './search-bar'
export default function Page() {
return (
<>
<Header />
<Suspense fallback={<div>Loading...</div>}>
<SearchBar /> {/* 'use client' + useSearchParams() */}
</Suspense>
<Article />
</>
)
}
Which hooks need a boundary
Click a cell to see the rule.
Suspense boundaryRequired
| Hook | Static | Dynamic [slug] | Dynamic + generateStaticParams |
|---|
View source
Switch mode and phase, then edit ?q= in the toolbar.
view-source:/search?q=linenServer
Why it matters, pros and cons
Why it matters
The query is unknown at prerender, so its reader bails out to a boundary.
Pros
- Header and article stay in prerendered HTML.
- The page still reads if JS fails.
- The fallback reserves the slot, no jump.
Cons
- The fallback shows until hydration; size it to match.
- Need it on the server? Read the
searchParamsprop. useParams()anduseRouter()never need one.