Skip to main content

useSearchParams

useSearchParams is a Client Component hook that lets you read the current URL's query string.

useSearchParams returns a read-only version of the URLSearchParams interface.

'use client'

import { useSearchParams } from 'next/navigation'

export default function SearchBar() {
const searchParams = useSearchParams()

const search = searchParams.get('search')

// URL -> `/dashboard?search=my-project`
// `search` -> 'my-project'
return <>Search: {search}</>
}
'use client'

import { useSearchParams } from 'next/navigation'

export default function SearchBar() {
const searchParams = useSearchParams()

const search = searchParams.get('search')

// URL -> `/dashboard?search=my-project`
// `search` -> 'my-project'
return <>Search: {search}</>
}

Parameters​

const searchParams = useSearchParams()

useSearchParams does not take any parameters.

Returns​

useSearchParams returns a read-only version of the URLSearchParams interface, which includes utility methods for reading the URL's query string:

Good to know:

  • useSearchParams is a Client Component hook and is not supported in Server Components to prevent stale values during partial rendering.
  • If an application includes the /pages directory, useSearchParams will return ReadonlyURLSearchParams | null. The null value is for compatibility during migration since search params cannot be known during pre-rendering of a page that doesn't use getServerSideProps

Static Rendering​

If a route is statically rendered, calling useSearchParams will cause the Client Component tree up to the closest Suspense boundary to be client-side rendered.

This allows a part of the route to be statically rendered while the dynamic part that uses useSearchParams is client-side rendered.

We recommend wrapping the Client Component that uses useSearchParams in a <Suspense/> boundary. This will allow any Client Components above it to be statically rendered and sent as part of initial HTML. Example.

For example:

'use client'

import { useSearchParams } from 'next/navigation'

export default function SearchBar() {
const searchParams = useSearchParams()

const search = searchParams.get('search')

// This will not be logged on the server when using static rendering
console.log(search)

return <>Search: {search}</>
}
'use client'

import { useSearchParams } from 'next/navigation'

export default function SearchBar() {
const searchParams = useSearchParams()

const search = searchParams.get('search')

// This will not be logged on the server when using static rendering
console.log(search)

return <>Search: {search}</>
}
import { Suspense } from 'react'
import SearchBar from './search-bar'

// This component passed as a fallback to the Suspense boundary
// will be rendered in place of the search bar in the initial HTML.
// When the value is available during React hydration the fallback
// will be replaced with the `<SearchBar>` component.
function SearchBarFallback() {
return <>placeholder</>
}

export default function Page() {
return (
<>
<nav>
<Suspense fallback={<SearchBarFallback />}>
<SearchBar />
</Suspense>
</nav>
<h1>Dashboard</h1>
</>
)
}
import { Suspense } from 'react'
import SearchBar from './search-bar'

// This component passed as a fallback to the Suspense boundary
// will be rendered in place of the search bar in the initial HTML.
// When the value is available during React hydration the fallback
// will be replaced with the `<SearchBar>` component.
function SearchBarFallback() {
return <>placeholder</>
}

export default function Page() {
return (
<>
<nav>
<Suspense fallback={<SearchBarFallback />}>
<SearchBar />
</Suspense>
</nav>
<h1>Dashboard</h1>
</>
)
}

Behavior​

Dynamic Rendering​

If a route is dynamically rendered, useSearchParams will be available on the server during the initial server render of the Client Component.

For example:

'use client'

import { useSearchParams } from 'next/navigation'

export default function SearchBar() {
const searchParams = useSearchParams()

const search = searchParams.get('search')

// This will be logged on the server during the initial render
// and on the client on subsequent navigations.
console.log(search)

return <>Search: {search}</>
}
'use client'

import { useSearchParams } from 'next/navigation'

export default function SearchBar() {
const searchParams = useSearchParams()

const search = searchParams.get('search')

// This will be logged on the server during the initial render
// and on the client on subsequent navigations.
console.log(search)

return <>Search: {search}</>
}
import SearchBar from './search-bar'

export const dynamic = 'force-dynamic'

export default function Page() {
return (
<>
<nav>
<SearchBar />
</nav>
<h1>Dashboard</h1>
</>
)
}
import SearchBar from './search-bar'

export const dynamic = 'force-dynamic'

export default function Page() {
return (
<>
<nav>
<SearchBar />
</nav>
<h1>Dashboard</h1>
</>
)
}

Good to know: Setting the dynamic route segment config option to force-dynamic can be used to force dynamic rendering.

Server Components​

Pages​

To access search params in Pages (Server Components), use the searchParams prop.

Layouts​

Unlike Pages, Layouts (Server Components) do not receive the searchParams prop. This is because a shared layout is not re-rendered during navigation which could lead to stale searchParams between navigations. View detailed explanation.

Instead, use the Page searchParams prop or the useSearchParams hook in a Client Component, which is re-rendered on the client with the latest searchParams.

Examples​

Updating searchParams​

You can use useRouter or Link to set new searchParams. After a navigation is performed, the current page.js will receive an updated searchParams prop.

'use client'

export default function ExampleClientComponent() {
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()

// Get a new searchParams string by merging the current
// searchParams with a provided key/value pair
const createQueryString = useCallback(
(name: string, value: string) => {
const params = new URLSearchParams(searchParams.toString())
params.set(name, value)

return params.toString()
},
[searchParams]
)

return (
<>
<p>Sort By</p>

{/* using useRouter */}
<button
onClick={() => {
// <pathname>?sort=asc
router.push(pathname + '?' + createQueryString('sort', 'asc'))
}}
>
ASC
</button>

{/* using <Link> */}
<Link
href={
// <pathname>?sort=desc
pathname + '?' + createQueryString('sort', 'desc')
}
>
DESC
</Link>
</>
)
}
'use client'

export default function ExampleClientComponent() {
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()

// Get a new searchParams string by merging the current
// searchParams with a provided key/value pair
const createQueryString = useCallback(
(name, value) => {
const params = new URLSearchParams(searchParams)
params.set(name, value)

return params.toString()
},
[searchParams]
)

return (
<>
<p>Sort By</p>

{/* using useRouter */}
<button
onClick={() => {
// <pathname>?sort=asc
router.push(pathname + '?' + createQueryString('sort', 'asc'))
}}
>
ASC
</button>

{/* using <Link> */}
<Link
href={
// <pathname>?sort=desc
pathname + '?' + createQueryString('sort', 'desc')
}
>
DESC
</Link>
</>
)
}

Version History​

VersionChanges
v13.0.0useSearchParams introduced.