next-prerender-client-hook.mdx
title: Client navigation hook requires a Suspense boundary
Why This Error Occurred
When cacheComponents is enabled, Next.js prerenders as much of a route as possible before a request arrives. A Client Component used a navigation hook whose value was not available during that prerender, but the component was not inside a Suspense boundary.
This can happen with the following hooks:
useSearchParams, because the query string comes from the request URLuseParams,usePathname,useSelectedLayoutSegment, oruseSelectedLayoutSegmentswhen the route contains dynamic params that were not provided bygenerateStaticParams
These hooks are reactive during client navigation. If their initial value is not known while prerendering, Next.js needs a fallback to include in the static shell until the runtime value is available.
Possible Ways to Fix It
Wrap the Client Component in Suspense
Wrap the smallest subtree that uses the hook in a Suspense boundary. Next.js can then prerender the fallback and replace it with the Client Component when the runtime value is available.
Before:
import { Search } from './search'
export default function Page() {
return (
<main>
<h1>Dashboard</h1>
<Search />
</main>
)
}
'use client'
import { useSearchParams } from 'next/navigation'
export function Search() {
const searchParams = useSearchParams()
return <p>Search: {searchParams.get('q')}</p>
}
After:
import { Suspense } from 'react'
import { Search } from './search'
export default function Page() {
return (
<main>
<h1>Dashboard</h1>
<Suspense fallback={<p>Loading search...</p>}>
<Search />
</Suspense>
</main>
)
}
The fallback should be synchronous and deterministic. Place the boundary close to the component that uses the hook so the rest of the route can remain in the prerendered shell.
Prerender Known Dynamic Params
For hooks that derive their value from dynamic route params, use generateStaticParams when the possible values are known ahead of time:
export function generateStaticParams() {
return [{ slug: 'hello-world' }, { slug: 'release-notes' }]
}
export default function Page() {
return <BlogNavigation />
}
For the generated paths, useParams, usePathname, and the selected-layout-segment hooks can resolve during prerendering. Paths not returned by generateStaticParams may still require a Suspense boundary.
generateStaticParams does not provide search parameters. Components that use useSearchParams should be wrapped in Suspense when the route is prerendered.
Useful Links
Rendered from the public repository vercel/next.js on GitHub; content belongs to its authors. Cached for up to an hour.