Skip to main content

useSearchParams

useSearchParams 是一个客户端组件钩子,让你可以读取当前 URL 的查询字符串。

useSearchParams 返回 URLSearchParams 接口的只读版本。

app/dashboard/search-bar.tsx
'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}</>
}

参数​

const searchParams = useSearchParams()

useSearchParams 不接受任何参数。

返回值​

useSearchParams 返回 URLSearchParams 接口的只读版本,包括用于读取 URL 查询字符串的实用方法:

提示:

  • useSearchParams 是一个 客户端组件 钩子,在 服务端组件 中不支持,以防止在 部分渲染 期间出现过时的值。
  • 如果你想在服务端组件中基于搜索参数获取数据,通常更好的选择是读取相应页面的 searchParams 属性。然后你可以通过 props 将其传递给该页面内的任何组件(服务端或客户端)。
  • 如果应用程序包含 /pages 目录,useSearchParams 将返回 ReadonlyURLSearchParams | null。null 值是为了在迁移期间兼容,因为在预渲染不使用 getServerSideProps 的页面时无法知道搜索参数。

行为​

静态渲染​

如果路由是 静态渲染,调用 useSearchParams 将导致客户端组件树到最近的 Suspense 边界 进行客户端渲染。

这允许路由的一部分被静态渲染,而使用 useSearchParams 的动态部分进行客户端渲染。

我们建议将使用 useSearchParams 的客户端组件包装在 <Suspense/> 边界中。这将允许其上方的任何客户端组件被静态渲染并作为初始 HTML 的一部分发送。示例。

例如:

app/dashboard/search-bar.tsx
'use client'

import { useSearchParams } from 'next/navigation'

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

const search = searchParams.get('search')

// 使用静态渲染时,这不会在服务器上记录
console.log(search)

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

// 作为 Suspense 边界的回退传递的组件
// 将在初始 HTML 中代替搜索栏渲染。
// 当值在 React 水合期间可用时,回退
// 将被 `<SearchBar>` 组件替换。
function SearchBarFallback() {
return <>placeholder</>
}

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

提示:在开发环境中,所有页面都是按需渲染的,所以 useSearchParams 不会暂停。但是,如果在开发环境中工作的 静态页面 在客户端组件中使用了 useSearchParams 而没有直接或间接包装在 Suspense 边界中,预渲染将会失败。

动态渲染​

如果路由是 动态渲染,useSearchParams 将在客户端组件的初始服务器渲染期间在服务器上可用。

例如:

app/dashboard/search-bar.tsx
'use client'

import { useSearchParams } from 'next/navigation'

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

const search = searchParams.get('search')

// 这将在初始渲染期间在服务器上记录
// 并在后续导航时在客户端记录。
console.log(search)

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

export const dynamic = 'force-dynamic'

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

提示:将 dynamic 路由段配置选项 设置为 force-dynamic 可用于强制动态渲染。

服务端组件​

页面​

要在 页面(服务端组件)中访问搜索参数,请使用 searchParams 属性。

布局​

与页面不同,布局(服务端组件)不会接收 searchParams 属性。这是因为共享布局在 导航期间不会重新渲染,这可能导致导航之间的 searchParams 过时。查看 详细说明。

相反,使用页面的 searchParams 属性或在客户端组件中使用 useSearchParams 钩子,它会在客户端使用最新的 searchParams 重新渲染。

示例​

更新 searchParams​

你可以使用 useRouter 或 Link 来设置新的 searchParams。执行导航后,当前的 page.js 将接收更新的 searchParams 属性。

app/example-client-component.tsx
'use client'

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

// 通过合并当前的 searchParams 与提供的键/值对
// 获取新的 searchParams 字符串
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>

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

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

版本历史​

版本更改
v13.0.0引入了 useSearchParams。