useSearchParams
useSearchParams 是一个 Client Component hook,它允许你读取当前 URL 的查询字符串。
useSearchParams 返回 URLSearchParams 接口的只读版本。
'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 查询字符串的实用方法:
-
URLSearchParams.get():返回与搜索参数关联的第一个值。例如:URL searchParams.get("a")/dashboard?a=1'1'/dashboard?a=''/dashboard?b=3null/dashboard?a=1&a=2'1'- 使用getAll()获取所有值 -
URLSearchParams.has():返回一个布尔值,指示给定参数是否存在。例如:URL searchParams.has("a")/dashboard?a=1true/dashboard?b=3false -
了解更多关于
URLSearchParams的其他只读方法,包括getAll()、keys()、values()、entries()、forEach()和toString()。
值得注意的是:
useSearchParams是一个 Client Component hook,在 Server Components 中不受支持,以防止在部分渲染期间出现过期值。- 如果你想在 Server Component 中基于搜索参数获取数据,通常更好的选择是读取相应 Page 的
searchParamsprop。然后你可以通过 props 将其传递给该 Page 中的任何组件(Server 或 Client)。- 如果应用程序包含
/pages目录,useSearchParams将返回ReadonlyURLSearchParams | null。null值是为了迁移期间的兼容性,因为在不使用getServerSideProps的页面预渲染期间无法知道搜索参数
行为
静态渲染
如果路由是静态渲染的,调用 useSearchParams 将导致 Client Component 树直到最近的 Suspense 边界在客户端渲染。
这允许路由的一部分被静态渲染,而使用 useSearchParams 的动态部分在客户端渲染。
我们建议将使用 useSearchParams 的 Client Component 包装在 <Suspense/> 边界中。这将允许其上方的任何 Client Components 被静态渲染并作为初始 HTML 的一部分发送。示例。
例如:
'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}</>
}import { Suspense } from 'react'
import SearchBar from './search-bar'
// 这个作为 Suspense 边界的 fallback 传递的组件
// 将在初始 HTML 中代替搜索栏进行渲染。
// 当 React hydration 期间值可用时,fallback
// 将被 `<SearchBar>` 组件替换。
function SearchBarFallback() {
return <>placeholder</>
}
export default function Page() {
return (
<>
<nav>
<Suspense fallback={<SearchBarFallback />}>
<SearchBar />
</Suspense>
</nav>
<h1>Dashboard</h1>
</>
)
}值得注意的是:
- 在开发环境中,路由是按需渲染的,因此
useSearchParams不会挂起,没有Suspense的情况下可能看起来正常工作。- 在生产构建期间,从 Client Component 调用
useSearchParams的静态页面必须包装在Suspense边界中,否则构建将失败并出现 Missing Suspense boundary with useSearchParams 错误。- 如果你希望路由被动态渲染,优先在 Server Component 中首先使用
connection函数来等待传入的请求,这将排除下面的所有内容进行预渲染。查看动态渲染指南中使路由动态化的因素。- 如果你已经在 Server Component Page 中,考虑使用
searchParamsprop 并将值传递给 Client Components。- 你也可以将 Page
searchParamsprop 直接传递给 Client Component,并使用 React 的use()解包它。虽然这会挂起,所以 Client Component 应该用Suspense边界包装。
动态渲染
如果路由是动态渲染的,useSearchParams 将在 Client Component 的初始服务器渲染期间在服务器上可用。
例如:
'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}</>
}import { connection } from 'next/server'
import SearchBar from './search-bar'
export default async function Page() {
await connection()
return (
<>
<nav>
<SearchBar />
</nav>
<h1>Dashboard</h1>
</>
)
}值得注意的是:
- 以前,在页面上设置
export const dynamic = 'force-dynamic'用于强制动态渲染。优先使用connection(),因为它在语义上将动态渲染与传入请求绑定。
Server Components
Pages
要在 Pages(Server Components)中访问搜索参数,请使用 searchParams prop。
Layouts
与 Pages 不同,Layouts(Server Components)不会接收 searchParams prop。这是因为共享布局在导航期间不会重新渲染,这可能导致导航之间的 searchParams 过期。查看详细解释。
相反,使用 Page searchParams prop 或在 Client Component 中使用 useSearchParams hook,它会在客户端使用最新的 searchParams 重新渲染。
示例
更新 searchParams
你可以使用 useRouter 或 Link 来设置新的 searchParams。执行导航后,当前的 page.js 将收到更新的 searchParams prop。
'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>
</>
)
}版本历史
| Version | Changes |
|---|---|
v13.0.0 | 引入 useSearchParams。 |