跳到主要内容

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 | nullnull 值是为了在迁移期间兼容,因为在预渲染不使用 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

你可以使用 useRouterLink 来设置新的 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