Menu

useSearchParams

useSearchParams 是一个 客户端组件 hook,允许你读取当前 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}</>;
}
app/dashboard/search-bar.js
"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 查询字符串的实用方法:

值得注意的是

  • useSearchParams 是一个 客户端组件 hook,不支持 服务器组件,以防止在 部分渲染 期间出现陈旧值。
  • 如果应用程序包含 /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}</>;
}
app/dashboard/search-bar.js
"use client";
 
import { useSearchParams } from "next/navigation";
 
export default function SearchBar() {
  const searchParams = useSearchParams();
 
  const search = searchParams.get("search");
 
  // 在使用静态渲染时,这不会在服务器上记录
  console.log(search);
 
  return <>搜索: {search}</>;
}
app/dashboard/page.tsx
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>
    </>
  );
}
app/dashboard/page.js
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>
    </>
  );
}

行为

动态渲染

如果路由是 动态渲染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}</>;
}
app/dashboard/search-bar.js
"use client";
 
import { useSearchParams } from "next/navigation";
 
export default function SearchBar() {
  const searchParams = useSearchParams();
 
  const search = searchParams.get("search");
 
  // 这将在初始渲染期间在服务器上记录
  // 并在后续导航中在客户端记录
  console.log(search);
 
  return <>搜索: {search}</>;
}
app/dashboard/page.tsx
import SearchBar from "./search-bar";
 
export const dynamic = "force-dynamic";
 
export default function Page() {
  return (
    <>
      <nav>
        <SearchBar />
      </nav>
      <h1>仪表板</h1>
    </>
  );
}
app/dashboard/page.js
import SearchBar from "./search-bar";
 
export const dynamic = "force-dynamic";
 
export default function Page() {
  return (
    <>
      <nav>
        <SearchBar />
      </nav>
      <h1>仪表板</h1>
    </>
  );
}

值得注意的是:设置 dynamic 路由段配置选项force-dynamic 可以强制动态渲染。

服务器组件

页面

要在 页面(服务器组件)中访问搜索参数,请使用 searchParams 属性。

布局

与页面不同,布局(服务器组件) 接收 searchParams 属性。这是因为共享布局在导航期间 不会重新渲染,这可能导致 searchParams 在导航之间陈旧。查看 详细解释

相反,在客户端组件中使用页面 searchParams 属性或 useSearchParams hook,该组件在客户端使用最新的 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>排序方式</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>
    </>
  );
}
app/example-client-component.js
"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.0useSearchParams 引入。