rembrembdocs

useRouter

Last updated April 23, 2026

The useRouter hook allows you to programmatically change routes inside Client Components.

Recommendation: Use the <Link> component for navigation unless you have a specific requirement for using useRouter.

app/example-client-component.tsx

JavaScriptTypeScript

'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()

Good to know:

  • You must not send untrusted or unsanitized URLs to router.push or router.replace, as this can open your site to cross-site scripting (XSS) vulnerabilities. For example, javascript: URLs sent to router.push or router.replace will be executed in the context of your page.
  • The <Link> component automatically prefetch routes as they become visible in the viewport.
  • refresh() could re-produce the same result if fetch requests are cached. Other Request-time APIs like cookies and headers could also change the response.
  • The onInvalidate callback is called at most once per prefetch request. It signals when you may want to trigger a new prefetch for updated route data.

Migrating from next/router

View the full migration guide.

Examples

Router events

You can listen for page changes by composing other Client Component hooks like usePathname and 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)
    // You can now use the current URL
    // ...
  }, [pathname, searchParams])
 
  return '...'
}

Which can be imported into a 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>
  )
}

Good to know: <NavigationEvents> is wrapped in a Suspense boundary becauseuseSearchParams() causes client-side rendering up to the closest Suspense boundary during prerendering. Learn more.

Disabling scroll to top

By default, Next.js will scroll to the top of the page when navigating to a new route. You can disable this behavior by passing scroll: false to router.push() or router.replace().

app/example-client-component.tsx

JavaScriptTypeScript

'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 History

VersionChanges
v15.4.0Optional onInvalidate callback for router.prefetch introduced
v13.0.0useRouter from next/navigation introduced.

Was this helpful?