The useRouter hook lets a Client Component change routes in code, instead of relying on a reader clicking a link. Call it inside an event handler, such as after a button click finishes some logic or a form submits.
// app/search/search-form.tsx
"use client";
import { useRouter } from "next/navigation";
export default function SearchForm() {
const router = useRouter();
return (
<button onClick={() => router.push("/search/results")}>View results</button>
);
}This hook only works in a Client Component, which is why the file starts with a client directive. Clicking the button changes the URL to the results page and swaps in the new content, the same client-side transition a plain link click triggers.
A common mistake is importing this hook from the wrong package. That older import path belongs to the Pages Router and exposes a different hook entirely, so using it inside an App Router project causes an error. Always import from next/navigation in the App Router, never from next/router.
The four methods, one at a time
Each method changes the current route differently. Pick the one that matches what the reader should actually see happen.
| Method | What it does |
|---|---|
| push | Navigates to a new route and adds a history entry |
| replace | Navigates to a new route without adding a history entry |
| refresh | Re-fetches the current route's data from the server |
back() / forward() | Moves through browser history like the browser's own buttons |
Push and replace both accept an options object as a second argument, such as one that turns off the default scroll-to-top behavior. Neither method takes a separate path string as a second positional argument the way an older router once did.
When replace is the right call
Reach for replace instead of push when the current entry should not stay in history, such as sending a signed-in reader away from a login page after they sign in.
// app/login/redirect-button.tsx
"use client";
import { useRouter } from "next/navigation";
export default function GoToDashboard() {
const router = useRouter();
return (
<button onClick={() => router.replace("/dashboard")}>Continue</button>
);
}Clicking this button sends the reader to the dashboard, and pressing the browser's back button afterward skips the login page entirely instead of returning to it. That is the visible difference between the two methods.
Getting fresh data with refresh
The refresh method re-runs the current route's data fetching and re-renders its Server Components, without a full browser reload and without losing client-side state such as an open menu or a text field's value. It is the method to reach for right after a mutation changes data the current page depends on, since navigating alone will not pick up that change.
For the exact reason navigating alone does not refresh stale data, see Why router.push() Does Not Refresh Data in Next.js. To compare this hook against server-side redirects, read useRouter vs redirect in Next.js: Client vs Server Navigation.
Rune AI
Key Insights
- Import useRouter from next/navigation in the App Router, not from next/router.
- useRouter only works in a Client Component, so its file needs the use client directive.
- push adds a new history entry, replace swaps the current one.
- refresh re-fetches the current route's data from the server without a full reload.
- back and forward move through browser history the same way the browser buttons do.
Frequently Asked Questions
Why does my useRouter import not work?
Can I use useRouter in a Server Component?
Does push accept a second argument like the old Pages Router did?
Conclusion
useRouter gives a Client Component direct control over navigation. Push and replace move between routes, refresh pulls fresh server data into the current route, and back or forward move through browser history, all without a full page reload.
More in this topic
`generateMetadata` Explained with Real Examples
What generateMetadata does, when it runs, and how to use it for real routes: awaited params, deduplicated data fetching, extending parent metadata, and returning a 404 from metadata.
Canonical URLs in Next.js: `metadataBase`, `alternates.canonical`, and Dynamic Pages
How canonical URLs work in the Next.js App Router: setting metadataBase once, writing alternates.canonical per route, handling dynamic segments, and what happens when the base URL is missing.
Open Graph and Twitter Card Metadata in Next.js
How to write Open Graph and Twitter card metadata in the Next.js App Router: the openGraph and twitter fields, automatic card defaults, article tags, and image merge rules.