While Next.js excels at declarative routing using its file-based system, there are many scenarios where you'll need to navigate programmatically within your application. This could be after a successful form submission, when a user clicks a specific button, or based on certain application logic. Next.js provides the next/router module to handle these programmatic navigation needs.
The core of programmatic navigation in Next.js lies within the useRouter hook. This hook provides access to the router object, which contains methods for manipulating the browser's URL and controlling navigation. You can use useRouter within any functional component.
import { useRouter } from 'next/router';
function MyComponent() {
const router = useRouter();
// ... rest of your component
}The router object exposed by useRouter has several key methods for navigation. The most common are push and replace.
router.push(url, as, options): This method pushes a new URL onto the browser's history stack. This means the user can navigate back to the previous page using the browser's back button. The url argument is the actual path to navigate to, and as (optional) is for URL masking (e.g., displaying a pretty URL while internally navigating to a different one). The options object can include scroll: false to prevent scrolling to the top of the new page.
import { useRouter } from 'next/router';
function NavigationButton() {
const router = useRouter();
const handleClick = () => {
router.push('/about');
};
return <button onClick={handleClick}>Go to About Page</button>;
}router.replace(url, as, options): This method replaces the current entry in the browser's history stack with the new URL. This is useful for scenarios like redirects after login, where you don't want the user to be able to go back to the login page after they've been authenticated. The arguments are similar to push.
import { useRouter } from 'next/router';
function LoginForm() {
const router = useRouter();
const handleSubmit = async (e) => {
e.preventDefault();
// Simulate login logic
const isLoggedIn = true;
if (isLoggedIn) {
router.replace('/dashboard');
}
};
return <form onSubmit={handleSubmit}>...</form>;
}You can also pass dynamic route parameters to router.push and router.replace. These parameters are defined in your file-based routing (e.g., pages/posts/[id].js) and can be accessed programmatically.
import { useRouter } from 'next/router';
function PostListItem({ post }) {
const router = useRouter();
const goToPost = () => {
router.push(`/posts/${post.id}`);
};
return (
<div onClick={goToPost}>
<h2>{post.title}</h2>
</div>
);
}The router object also provides methods for navigating back and forth in the history, similar to browser buttons.
router.back(): Navigates to the previous page in the history stack.
import { useRouter } from 'next/router';
function GoBackButton() {
const router = useRouter();
return <button onClick={() => router.back()}>Go Back</button>;
}router.forward(): Navigates to the next page in the history stack (if available).
import { useRouter } from 'next/router';
function GoForwardButton() {
const router = useRouter();
return <button onClick={() => router.forward()}>Go Forward</button>;
}For server-side navigation or when you don't have access to the useRouter hook (e.g., in _app.js or custom server logic), you can import Router directly from next/router and use its static methods. However, the useRouter hook is the preferred method for client-side navigation within components.
import Router from 'next/router';
function handleLogout() {
// Perform logout actions
Router.replace('/login');
}Understanding programmatic navigation is crucial for building dynamic and interactive user experiences in your Next.js applications. It allows you to control user flow based on application state and user actions, leading to a more seamless and intuitive interface.
graph TD
A[Start Component] --> B{Use useRouter Hook}
B --> C[Get router Object]
C --> D{Trigger Navigation Event}
D -- Button Click/Form Submit --> E{Call router.push() or router.replace()}
E --> F[Update Browser URL]
F --> G[Render New Page/Component]