useRouter
useRouter hook 允许你在 Client Components 中以编程方式更改路由。
建议: 除非你有使用
useRouter的特定需求,否则请使用<Link>组件 进行导航。
app/example-client-component.tsx
TypeScript
'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():刷新当前路由。向服务器发起新请求,重新获取数据请求,并重新渲染 Server Components。客户端将合并更新的 React Server Component payload,而不会丢失未受影响的客户端 React 状态(例如useState)或浏览器状态(例如滚动位置)。router.prefetch(href: string, options?: { onInvalidate?: () => void }):预取提供的路由,以实现更快的客户端过渡。可选的onInvalidate回调会在预取数据变得过时时被调用。router.back():在浏览器的历史堆栈中导航回上一个路由。router.forward():在浏览器的历史堆栈中向前导航到下一页。
值得注意的是:
- 你不能向
router.push或router.replace发送不受信任或未清理的 URL,因为这可能会使你的站点面临跨站脚本(XSS)漏洞。例如,发送到router.push或router.replace的javascript:URL 将在你的页面上下文中执行。<Link>组件会在路由在视口中变得可见时自动预取路由。- 如果 fetch 请求被缓存,
refresh()可能会重新产生相同的结果。其他 Dynamic API(如cookies和headers)也可能改变响应。onInvalidate回调每个预取请求最多被调用一次。它会在你可能想要触发新的预取以获取更新的路由数据时发出信号。
从 next/router 迁移
- 使用 App Router 时,
useRouterhook 应该从next/navigation而不是next/router导入 pathname字符串已被移除,并被usePathname()替代query对象已被移除,并被useSearchParams()替代router.events已被替换。见下文。
Examples
Router events
你可以通过组合其他 Client Component hooks(如 usePathname 和 useSearchParams)来监听页面变化。
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 '...'
}可以将其导入到 layout 中。
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
TypeScript
'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>
)
}版本历史
| Version | Changes |
|---|---|
v15.4.0 | router.prefetch 的可选 onInvalidate 回调引入 |
v13.0.0 | 引入来自 next/navigation 的 useRouter。 |