useSearchParams
useSearchParams
是一个客户端组件 (Client Component) 钩子,用于读取当前 URL 的查询字符串 (query string)。
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}</>
}
'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}</>
}
参数
const searchParams = useSearchParams()
useSearchParams
不接受任何参数。
返回值
useSearchParams
返回 URLSearchParams
接口的只读版本,包含以下用于读取 URL 查询字符串的实用方法:
-
URLSearchParams.get()
: 返回与搜索参数关联的第一个值。例如:URL searchParams.get("a")
/dashboard?a=1
'1'
/dashboard?a=
''
/dashboard?b=3
null
/dashboard?a=1&a=2
'1'
- 使用getAll()
获取所有值 -
URLSearchParams.has()
: 返回布尔值表示参数是否存在。例如:URL searchParams.has("a")
/dashboard?a=1
true
/dashboard?b=3
false
-
了解更多
URLSearchParams
的其他只读方法,包括getAll()
,keys()
,values()
,entries()
,forEach()
和toString()
。
须知:
useSearchParams
是一个客户端组件 (Client Component) 钩子,不支持在服务端组件 (Server Components) 中使用,以防止部分渲染 (partial rendering) 时出现陈旧值。- 如果应用包含
/pages
目录,useSearchParams
将返回ReadonlyURLSearchParams | null
。null
值是为了迁移兼容性,因为在未使用getServerSideProps
的页面预渲染期间无法获取搜索参数。
行为
静态渲染 (Static Rendering)
如果路由是静态渲染,调用 useSearchParams
会导致从客户端组件树向上到最近的 Suspense
边界都在客户端渲染。
这使得路由的一部分可以静态渲染,而使用 useSearchParams
的动态部分则在客户端渲染。
我们建议将使用 useSearchParams
的客户端组件包裹在 <Suspense/>
边界中。这样可以让其上方的客户端组件作为初始 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}</>
}
'use client'
import { useSearchParams } from 'next/navigation'
export default function SearchBar() {
const searchParams = useSearchParams()
const search = searchParams.get('search')
// 使用静态渲染时,这不会在服务端记录
console.log(search)
return <>搜索: {search}</>
}
import { Suspense } from 'react'
import SearchBar from './search-bar'
// 作为 Suspense 边界回退传递的组件
// 将在初始 HTML 中替代搜索栏渲染。
// 当 React 水合期间值可用时,
// 回退将被 `<SearchBar>` 组件替换。
function SearchBarFallback() {
return <>占位符</>
}
export default function Page() {
return (
<>
<nav>
<Suspense fallback={<SearchBarFallback />}>
<SearchBar />
</Suspense>
</nav>
<h1>仪表盘</h1>
</>
)
}
import { Suspense } from 'react'
import SearchBar from './search-bar'
// 作为 Suspense 边界回退传递的组件
// 将在初始 HTML 中替代搜索栏渲染。
// 当 React 水合期间值可用时,
// 回退将被 `<SearchBar>` 组件替换。
function SearchBarFallback() {
return <>占位符</>
}
export default function Page() {
return (
<>
<nav>
<Suspense fallback={<SearchBarFallback />}>
<SearchBar />
</Suspense>
</nav>
<h1>仪表盘</h1>
</>
)
}
动态渲染 (Dynamic Rendering)
如果路由是动态渲染,useSearchParams
将在客户端组件的初始服务端渲染期间可用。
例如:
'use client'
import { useSearchParams } from 'next/navigation'
export default function SearchBar() {
const searchParams = useSearchParams()
const search = searchParams.get('search')
// 这会在初始渲染时在服务端记录,
// 并在后续导航时在客户端记录。
console.log(search)
return <>搜索: {search}</>
}
'use client'
import { useSearchParams } from 'next/navigation'
export default function SearchBar() {
const searchParams = useSearchParams()
const search = searchParams.get('search')
// 这会在初始渲染时在服务端记录,
// 并在后续导航时在客户端记录。
console.log(search)
return <>搜索: {search}</>
}
import SearchBar from './search-bar'
export const dynamic = 'force-dynamic'
export default function Page() {
return (
<>
<nav>
<SearchBar />
</nav>
<h1>仪表盘</h1>
</>
)
}
import SearchBar from './search-bar'
export const dynamic = 'force-dynamic'
export default function Page() {
return (
<>
<nav>
<SearchBar />
</nav>
<h1>仪表盘</h1>
</>
)
}
须知: 设置
dynamic
路由段配置选项 为force-dynamic
可以强制动态渲染。
服务端组件 (Server Components)
页面 (Pages)
要在页面 (Pages)(服务端组件)中访问搜索参数,请使用 searchParams
属性。
布局 (Layouts)
与页面不同,布局 (Layouts)(服务端组件)不会接收 searchParams
属性。这是因为共享布局在导航期间不会重新渲染,可能导致导航之间的 searchParams
陈旧。查看详细解释。
替代方案是在客户端组件中使用页面 searchParams
属性或 useSearchParams
钩子,这样可以在客户端重新渲染时获取最新的 searchParams
。
示例
更新 searchParams
您可以使用 useRouter
或 Link
来设置新的 searchParams
。执行导航后,当前的 page.js
将接收更新的 searchParams
属性。
'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>排序方式</p>
{/* 使用 useRouter */}
<button
onClick={() => {
// <pathname>?sort=asc
router.push(pathname + '?' + createQueryString('sort', 'asc'))
}}
>
升序
</button>
{/* 使用 <Link> */}
<Link
href={
// <pathname>?sort=desc
pathname + '?' + createQueryString('sort', 'desc')
}
>
降序
</Link>
</>
)
}
'use client'
export default function ExampleClientComponent() {
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()
// 通过合并当前 searchParams 与提供的键值对
// 获取新的 searchParams 字符串
const createQueryString = useCallback(
(name, value) => {
const params = new URLSearchParams(searchParams)
params.set(name, value)
return params.toString()
},
[searchParams]
)
return (
<>
<p>排序方式</p>
{/* 使用 useRouter */}
<button
onClick={() => {
// <pathname>?sort=asc
router.push(pathname + '?' + createQueryString('sort', 'asc'))
}}
>
升序
</button>
{/* 使用 <Link> */}
<Link
href={
// <pathname>?sort=desc
pathname + '?' + createQueryString('sort', 'desc')
}
>
降序
</Link>
</>
)
}
版本历史
版本 | 变更 |
---|---|
v13.0.0 | 引入 useSearchParams 。 |