How to fix NextRouter was not mounted in React

ReactINTERMEDIATEHIGHUpdated Dec 8, 2025· 169 views

Navigation errors in Next.js pages directory typically occur when using the wrong useRouter import or attempting to use App Router features in pages. This happens because Next.js has two routing systems with different APIs and imports, and mixing them causes runtime failures.

Quick fix

Fixes NextRouter was not mounted

// ❌ Wrong - This is for App Router
import { useRouter } from 'next/navigation';

// ✅ Correct - This is for Pages Router
import { useRouter } from 'next/router';

function MyPage() {
  const router = useRouter();
  // Now you can use router.push(), router.pathname, router.query, etc.
  return <div>Current path: {router.pathname}</div>;
}

export default MyPage;
  1. Verify you are using the correct useRouter import for pages directory
  2. Ensure _app.js exists and is properly configured
  3. Use useRouter only inside page components or components rendered by them
  4. Avoid mixing App Router and Pages Router
react — error
// ❌ Wrong - This is for App Router
import { useRouter } from 'next/navigation';
// ✅ Correct - This is for Pages Router
import { useRouter } from 'next/router';
function MyPage() {
const router = useRouter();
// Now you can use router.push(), router.pathname, router.query, etc.
return <div>Current path: {router.pathname}</div>;
}
export default MyPage;
NextRouter was not mounted

What this error means

Next.js provides two different routing systems: the Pages Router (the traditional file-system based router) and the App Router (introduced in Next.js 13). Each has its own useRouter hook with different APIs and behaviors. The "NextRouter was not mounted" error occurs when you try to use the useRouter hook from pages in a context where it isn't available, or when you're mixing imports between the two routing systems. The pages directory expects the useRouter hook from 'next/router', while the app directory uses useRouter from 'next/navigation'. This error is Next.js's way of telling you that the Router context hasn't been initialized for the current component. Since useRouter is a hook that depends on React's Context API, it requires the Router provider to be present in the component tree, which is only set up properly when you're using the correct router import for your routing system.

Typical symptoms

  • Console shows error: "NextRouter was not mounted. Make sure you have next/router imported in _app.ts" or similar
  • useRouter hook returns undefined or throws error when called
  • Navigation with router.push() or router.pathname fails silently
  • router.query is empty or undefined even though URL has query parameters
  • Importing useRouter from wrong package causes runtime errors
  • Pages fail to navigate when both app and pages directories exist in project
  • useRouter works in some pages but not in others without obvious reason

Common causes

  1. Importing useRouter from "next/navigation" (App Router) instead of "next/router" (Pages Router)
  2. Trying to use useRouter in a component that is not wrapped by Next.js Router provider
  3. Using useRouter in static generation context without proper client-side boundary
  4. App directory exists in project, confusing Next.js about which routing system to use
  5. Missing or improperly configured _app.js file that should provide Router context in pages directory
  6. Using useRouter in server-side code or getServerSideProps where Router context is unavailable
  7. Calling useRouter at the module level instead of inside a component function
  8. Router context not properly initialized due to build configuration issues

How to fix "NextRouter was not mounted"

1Verify you are using the correct useRouter import for pages directory

The Pages Router requires useRouter from 'next/router', not from 'next/navigation'. Check all your imports:

jsx
// ❌ Wrong - This is for App Router
import { useRouter } from 'next/navigation';

// ✅ Correct - This is for Pages Router
import { useRouter } from 'next/router';

function MyPage() {
  const router = useRouter();
  // Now you can use router.push(), router.pathname, router.query, etc.
  return <div>Current path: {router.pathname}</div>;
}

export default MyPage;

Make sure all files in your pages directory use 'next/router' and never use 'next/navigation' unless you're in the app directory.

2Ensure _app.js exists and is properly configured

The Pages Router requires an _app.js or _app.tsx file at the root of your pages directory. This file initializes the Router context for all pages:

jsx
// pages/_app.js
import type { AppProps } from 'next/app';

function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />;
}

export default MyApp;

Without this file, the Router context won't be initialized, and useRouter will fail. If you have a custom _app.js, make sure it's properly exporting the component as the default export.

3Use useRouter only inside page components or components rendered by them

The useRouter hook only works when called from within a component tree that is rendered by Next.js pages. You cannot use it in:
- Standalone utility files
- Components used outside of page rendering
- getServerSideProps or getStaticProps functions

jsx
// ❌ Wrong - useRouter won't work in utility file
// lib/utils.ts
export function handleNavigation() {
  const router = useRouter(); // Error!
}

// ✅ Correct - useRouter works inside page components
// pages/my-page.js
import { useRouter } from 'next/router';

export default function MyPage() {
  const router = useRouter();
  
  const handleClick = () => {
    router.push('/other-page');
  };
  
  return <button onClick={handleClick}>Navigate</button>;
}

If you need router functionality in utility files, pass the router instance as a parameter from the component that has access to it.

4Avoid mixing App Router and Pages Router

If your project has both app and pages directories, Next.js may become confused about which routing system is primary. To fix this:

Option 1: Use only Pages Router - Delete the app directory if you're not using App Router features:

bash
# If you're committed to Pages Router
rm -rf app/

Option 2: Use only App Router - Migrate all pages to the app directory and delete pages directory.

Option 3: Migration with next/compat/router - If gradually migrating, use the compatibility router:

jsx
import { useRouter } from 'next/compat/router';

function MyComponent() {
  const router = useRouter();
  return <div>{router?.pathname}</div>;
}

Mixing the two systems in one project causes unpredictable behavior and context initialization errors.

5Check that Router hooks are called inside function components

useRouter must be called inside a React functional component, not at the module level or in class components:

jsx
// ❌ Wrong - Called at module level
import { useRouter } from 'next/router';
const router = useRouter(); // Error!

function MyPage() {
  return <div>{router.pathname}</div>;
}

// ✅ Correct - Called inside component
import { useRouter } from 'next/router';

function MyPage() {
  const router = useRouter();
  return <div>{router.pathname}</div>;
}

// ✅ Also correct - In class component using withRouter wrapper
import { withRouter } from 'next/router';
import React from 'react';

class MyPage extends React.Component {
  render() {
    return <div>{this.props.router.pathname}</div>;
  }
}

export default withRouter(MyPage);
6Handle router readiness before accessing router properties

When a page first loads, the router may not be fully ready. Check router.isReady before accessing router.query, router.pathname, or other properties:

jsx
import { useRouter } from 'next/router';

function MyPage() {
  const router = useRouter();
  
  // ❌ Wrong - router.query might be empty before ready
  const id = router.query.id;
  
  // ✅ Correct - Check isReady first
  if (!router.isReady) {
    return <div>Loading...</div>;
  }
  
  const id = router.query.id;
  return <div>Product ID: {id}</div>;
}

export default MyPage;

Alternatively, use useEffect to handle router-dependent logic:

jsx
useEffect(() => {
  if (router.isReady) {
    // Access router.query safely here
    const id = router.query.id;
  }
}, [router.isReady, router.query]);
7Verify build and restart dev server

After making changes, rebuild your Next.js project and restart the development server:

bash
# Stop the current dev server (Ctrl+C)

# Clean build artifacts
rm -rf .next

# Restart dev server
npm run dev

# Or for production build
npm run build
npm run start

Sometimes the issue is just stale build cache. A clean rebuild and server restart often resolves the problem. If you made changes to _app.js, restart is essential for the new Router context provider to take effect.

Advanced notes

The Router context in Next.js pages directory is provided by the _app component and uses React's Context API internally. When you call useRouter, it accesses this context. If the context is undefined (not mounted), it means either the _app.js file is missing, you're using the wrong import, or you're calling useRouter outside of a component tree that has the context provider.

For gradual migrations from Pages to App Router, Next.js provides next/compat/router which wraps the useRouter hook to work in both contexts. This allows you to incrementally adopt App Router features while maintaining Pages Router in some parts of your application.

When working with dynamic routes in pages directory (like pages/post/[id].js), the router.query object is populated asynchronously after the page mounts. Use router.isReady to safely determine when dynamic route segments are available. This is different from getStaticProps getStaticPaths which receive params synchronously.

In Next.js 13+, if you have both directories, the framework tries to intelligently route requests, but this can be fragile. The app directory takes precedence for overlapping routes. Use explicit routing strategies: commit fully to App Router or keep Pages Router only.

Frequently asked questions

What does "NextRouter was not mounted" mean?
js 13). Each has its own useRouter hook with different APIs and behaviors. The "NextRouter was not mounted" error occurs when you try to use the useRouter hook from pages in a context where it isn't available, or when you're mixing imports between the two routing systems.
How do I fix "NextRouter was not mounted"?
Navigation errors in Next.js pages directory typically occur when using the wrong useRouter import or attempting to use App Router features in pages. This happens because Next.js has two routing systems with different APIs and imports, and mixing them causes runtime failures.
What causes "NextRouter was not mounted"?
Importing useRouter from "next/navigation" (App Router) instead of "next/router" (Pages Router) Trying to use useRouter in a component that is not wrapped by Next.js Router provider Using useRouter in static generation context without proper client-side boundary
Is the "NextRouter was not mounted" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading