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 查询字符串的实用方法:

须知:

行为

静态渲染 (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

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