useSearchParams 是一个 客户端组件 (Client Component) Hook,它允许你读取当前 URL 的 查询字符串 (query string)。
useSearchParams 返回 URLSearchParams 接口的只读 (read-only) 版本。
'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}</>
}const searchParams = useSearchParams()useSearchParams 不接受任何参数。
useSearchParams 返回 URLSearchParams 接口的只读 (read-only) 版本,它包含用于读取 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 的其他只读 (read-only) 方法,包括 getAll()、keys()、values()、entries()、forEach() 和 toString()。
须知 (Good to know):
useSearchParams是一个 客户端组件 (Client Component) Hook,不支持在 服务器组件 (Server Components) 中使用,以防止在 部分渲染 (partial rendering) 期间出现陈旧的值。- 如果你想在服务器组件中根据搜索参数获取数据,通常更好的选择是读取相应 Page 的
searchParams属性。然后,你可以通过 props 将其传递给该 Page 中的任何组件(服务器或客户端)。- 如果应用程序包含
/pages目录,useSearchParams将返回ReadonlyURLSearchParams | null。null值是为了在迁移期间保持兼容性,因为对于不使用getServerSideProps的页面,在预渲染期间无法得知搜索参数。
如果一个路由是 静态渲染 的,调用 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')
// 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>
</>
)
}须知 (Good to know):
- 在开发环境中,路由是按需渲染的,因此
useSearchParams不会暂停,并且在没有Suspense的情况下似乎也能正常工作。- 在生产构建期间,从客户端组件调用
useSearchParams的 静态页面 必须包裹在Suspense边界中,否则构建将因 Missing Suspense boundary with useSearchParams 错误而失败。- 如果你打算动态渲染路由,请优先在服务器组件中使用
connection函数来等待传入的请求,这会将下面的所有内容排除在预渲染之外。请参阅 动态渲染指南 中关于什么使路由动态化的内容。- 如果你已在服务器组件 Page 中,请考虑使用
searchParams属性 并将值传递给客户端组件。- 你也可以将 Page 的
searchParams属性 直接传递给客户端组件,并使用 React 的use()解包。尽管这会导致暂停,因此客户端组件应该包裹在Suspense边界中。
如果一个路由是 动态渲染 的,useSearchParams 将在客户端组件的初始服务器渲染期间在服务器上可用。
例如:
'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 { connection } from 'next/server'
import SearchBar from './search-bar'
export default async function Page() {
await connection()
return (
<>
<nav>
<SearchBar />
</nav>
<h1>Dashboard</h1>
</>
)
}import { connection } from 'next/server'
import SearchBar from './search-bar'
export default async function Page() {
await connection()
return (
<>
<nav>
<SearchBar />
</nav>
<h1>Dashboard</h1>
</>
)
}须知 (Good to know):
- 以前,通过在页面上设置
export const dynamic = 'force-dynamic'来强制动态渲染。现在,请优先使用connection(),因为它在语义上将动态渲染与传入请求关联起来。
要在 页面 (Pages)(服务器组件)中访问搜索参数,请使用 searchParams 属性。
与页面不同,布局 (Layouts)(服务器组件)不会接收 searchParams 属性。这是因为共享布局在 导航期间不会重新渲染,这可能导致导航之间 searchParams 过期。查看 详细解释。
相反,请在客户端组件中使用 Page 的 searchParams 属性或 useSearchParams Hook,它会在客户端使用最新的 searchParams 重新渲染。
searchParams你可以使用 useRouter 或 Link 来设置新的 searchParams。执行导航后,当前的 page.js 将接收到更新的 searchParams 属性。
'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>
</>
)
}| 版本 | 更改 |
|---|---|
v13.0.0 | 引入 useSearchParams。 |