Skip to content

Next.js: next/router vs next/navigation

Problem Statement

When working with Next.js routing, you'll encounter two similar-looking packages: next/router and next/navigation. Both expose a useRouter() hook, but they behave differently and are not interchangeable. This often causes confusion about when to use each package and why Next.js maintains two separate routing modules. Understanding this distinction is crucial to avoid errors and ensure proper navigation behavior in your application.

Core Difference Explained

next/router and next/navigation belong to different Next.js routing paradigms:

Pages Router (next/router)

  • Used exclusively in Next.js applications using the traditional pages directory structure
  • Works with both Client and Server Components
  • Provides a full-featured router object with extensive functionality
  • Installation: npm install next@^12

App Router (next/navigation)

  • Designed for Next.js applications using the modern app directory (introduced in Next.js 13)
  • Optimized for Server Components and React Suspense
  • Offers a lightweight API with essential navigation capabilities
  • Installation: npm install next@^13

WARNING

Do not mix APIs across routers: Using next/router in an App Router project will throw:

sh
Error: NextRouter was not mounted. https://nextjs.org/docs/messages/next-router-not-mounted

Practical Usage

Pages Router Implementation

jsx
// File location: /pages/about.js
import { useRouter } from 'next/router';

export default function AboutPage() {
  const router = useRouter();
  
  // Access query parameters
  console.log(router.query.id);
  
  return (
    <div>
      <h1>About Page</h1>
      <button onClick={() => router.push('/contact')}>
        Go to Contact
      </button>
    </div>
  );
}

App Router Implementation

jsx
// File location: /app/about/page.jsx
'use client'; // Client Component required for hooks

import { useRouter } from 'next/navigation';

export default function AboutPage() {
  const router = useRouter();
  
  return (
    <div>
      <h1>About Page</h1>
      <button onClick={() => router.push('/contact')}>
        Go to Contact
      </button>
    </div>
  );
}

Key Differences in useRouter() Behavior

Featurenext/router (Pages)next/navigation (App)
File Structurepages/ directoryapp/ directory
Server ComponentsPartial supportFull support
Route Parametersrouter.query objectuseParams() hook
Navigation Methodspush(), replace()push(), replace()
Back/Forward Navigationback(), forward()No direct equivalent
Route Change EventsrouteChangeStart/CompleteNavigation APIs via suspense

Migration Guide

When moving from Pages Router to App Router:

  1. Replace imports:

    diff
    - import { useRouter } from 'next/router';
    + import { useRouter } from 'next/navigation';
  2. Refactor query access:
    Instead of router.query.id, use:

    jsx
    // App Router pattern
    import { useParams } from 'next/navigation';
    
    function Component() {
      const params = useParams();
      console.log(params.id);
    }
  3. Replace route detection:
    Migrate from router.pathname to:

    jsx
    import { usePathname } from 'next/navigation';
    
    function Component() {
      const pathname = usePathname();
    }
  4. Server redirects:
    In Server Components:

    js
    import { redirect } from 'next/navigation';
    
    async function fetchData() {
      const res = await fetch('/api/data');
      if (!res.ok) redirect('/error');
    }

Recommendations

  1. New projects should use the App Router (app/ directory + next/navigation)
  2. Existing Pages Router projects can continue using next/router
  3. Avoid mixing approaches within the same project
  4. Prefer App Router features for:
    • Server actions and mutations
    • React Suspense integrations
    • Streaming server rendering
    • Simpler code structure

TIP

When using next/navigation, navigation occurs through declarative links (<Link>) or imperative commands (router.push()). Always import Link separately:

jsx
import Link from 'next/link';

Best Practices Summary

ScenarioRecommendation
Migrating existing Pages appMaintain next/router
Building a new projectUse app/ + next/navigation
Server ComponentsUse next/navigation for redirects
Accessing URL parametersuseParams() in App Router
Navigation eventsSuspense APIs in App Router
Small static sitesEither (consider Pages Router)

For most modern Next.js development, the App Router and next/navigation provide better performance, cleaner code organization, and support for React's latest features. Always ensure your imports match your project's router structure to prevent runtime errors.