Menu

useRouter

useRouter hook 允许你在 客户端组件 中以编程方式更改路由。

推荐做法:除非有特定需求需要使用 useRouter,否则建议使用 <Link> 组件 进行导航。

app/example-client-component.tsx
"use client";
 
import { useRouter } from "next/navigation";
 
export default function Page() {
  const router = useRouter();
 
  return (
    <button type="button" onClick={() => router.push("/dashboard")}>
      Dashboard
    </button>
  );
}
app/example-client-component.js
"use client";
 
import { useRouter } from "next/navigation";
 
export default function Page() {
  const router = useRouter();
 
  return (
    <button type="button" onClick={() => router.push("/dashboard")}>
      Dashboard
    </button>
  );
}

useRouter()

  • router.push(href: string, { scroll: boolean }):执行客户端导航到提供的路由。在 浏览器的历史记录 堆栈中添加一个新条目。
  • router.replace(href: string, { scroll: boolean }):执行客户端导航到提供的路由,而不在 浏览器的历史记录堆栈 中添加新条目。
  • router.refresh():刷新当前路由。向服务器发出新请求,重新获取数据请求,并重新渲染服务端组件。客户端将合并更新的 React 服务端组件负载,而不会丢失未受影响的客户端 React(例如 useState)或浏览器状态(例如滚动位置)。
  • router.prefetch(href: string)预取 提供的路由,以便更快地进行客户端转换。
  • router.back():导航回浏览器历史记录堆栈中的上一个路由。
  • router.forward():导航到浏览器历史记录堆栈中的下一个页面。

值得注意的是

  • <Link> 组件会自动预取在视口中变得可见的路由。
  • refresh() 可能会在 fetch 请求被缓存时产生相同的结果。其他动态函数如 cookiesheaders 也可能改变响应。

next/router 迁移

  • 在使用 App Router 时,应从 next/navigation 而不是 next/router 导入 useRouter hook。
  • pathname 字符串已被移除,取而代之的是 usePathname()
  • query 对象已被移除,取而代之的是 useSearchParams()
  • router.events 已被替换。见下文

查看完整的迁移指南

示例

路由事件

你可以通过组合其他客户端组件 hook 如 usePathnameuseSearchParams 来监听页面变化。

app/components/navigation-events.js
"use client";
 
import { useEffect } from "react";
import { usePathname, useSearchParams } from "next/navigation";
 
export function NavigationEvents() {
  const pathname = usePathname();
  const searchParams = useSearchParams();
 
  useEffect(() => {
    const url = `${pathname}?${searchParams}`;
    console.log(url);
    // 你现在可以使用当前 URL
    // ...
  }, [pathname, searchParams]);
 
  return "...";
}

可以将其导入到布局中。

app/layout.js
import { Suspense } from "react";
import { NavigationEvents } from "./components/navigation-events";
 
export default function Layout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}
 
        <Suspense fallback={null}>
          <NavigationEvents />
        </Suspense>
      </body>
    </html>
  );
}

值得注意的是<NavigationEvents> 被包裹在一个 Suspense 边界 中,因为 useSearchParams()静态渲染 期间会导致客户端渲染到最近的 Suspense 边界。了解更多

禁用滚动恢复

默认情况下,Next.js 会在导航到新路由时滚动到页面顶部。你可以通过向 router.push()router.replace() 传递 scroll: false 来禁用此行为。

app/example-client-component.tsx
"use client";
 
import { useRouter } from "next/navigation";
 
export default function Page() {
  const router = useRouter();
 
  return (
    <button
      type="button"
      onClick={() => router.push("/dashboard", { scroll: false })}
    >
      Dashboard
    </button>
  );
}
app/example-client-component.jsx
"use client";
 
import { useRouter } from "next/navigation";
 
export default function Page() {
  const router = useRouter();
 
  return (
    <button
      type="button"
      onClick={() => router.push("/dashboard", { scroll: false })}
    >
      Dashboard
    </button>
  );
}

版本历史

版本变更
v13.0.0next/navigation 引入 useRouter