This concise article shows you how to fix a common error related to NextRouter
in Next.js
Table of Contents
The Problem
When working with Next.js 13 or a newer version of the framework, you might run into the following error:
Unhandled Runtime Error
Error: NextRouter was not mounted.
Screenshot:
The cause of the error is that you imported the useRouter
hook from next/router
.
The Solution
To solve the mentioned problem, you should always import useRouter
from next/navigation
instead of next/router
when working with pages and components inside the app
directory.
Other important things you should be aware of to avoid potential errors with useRouter
:
- All components in the
app
directory are server components by default, but hooks are only available on the client side. Thus, you must add theuse client
directive at the top of every file that involves hooks. - The
pathname
andquery
properties were removed from the router object. You should use theusePathname()
anduseSearchParams()
hooks instead.
Below is a complete and working example that demonstrates how to correctly and safely use the useRouter()
in Next.js 13 and above.
// app/pages.tsx
'use client';
import { useRouter } from 'next/navigation';
export default function Home() {
const router = useRouter();
const refreshPage = () => {
router.refresh();
};
return (
<div style={{ padding: 30 }}>
<h1 style={{ fontSize: 40 }}>Welcome to Sling Academy</h1>
<button
style={{
padding: '7px 30px',
background: 'green',
color: 'white',
}}
onClick={refreshPage}
>
Refresh this page
</button>
</div>
);
}
Screenshot:
If you’re working for a large company, it’s very likely that your boss requires you (or your team) to do unit tests when developing Next.js projects. This is the main point of the next section.
Mocking NextRoter for Unit Test
When you perform unit tests by using a library like Jest, you should mock NextRouter
to get through the potential errors related to this hook (including the problem above). A great solution is to use a package named next-router-mock
. Install it by running the following command:
npm i next-router-mock -D
Then use it as the following instructions:
// Jest Configuration
// For unit tests, the next-router-mock module can be used as a drop-in replacement for next/router:
jest.mock('next/router', () => require('next-router-mock'));
// You can do this once per spec file, or you can do this globally using setupFilesAfterEnv.
An alternative solution is to use the jest.mock()
function to replace the next/navigation
or next/router
module with a mock implementation.
Example:
// mock useRouter
jest.mock('next/router', () => ({
useRouter: jest.fn()
}));
// setup a new mocking function for push method
const pushMock = jest.fn();
// mock a return value on useRouter
useRouter.mockReturnValue({
query: {},
// return mock for push method
push: pushMock,
// ... add the props or methods you need
});
That’s it. Happy coding & have a nice day!