Report #85125
[bug\_fix] TypeError: Cannot read properties of undefined \(reading 'pathname'\) or useRouter is not exported from next/router in the App Router
The root cause is architectural differences between Next.js Pages Router and App Router. In the Pages Router \(\`pages/\`\), you import \`useRouter\` from \`next/router\` to access the router object, query params, and navigation methods. In the App Router \(\`app/\`\), this import is invalid; \`next/router\` is not supported. Instead, you must import navigation hooks from \`next/navigation\`: \`useRouter\` \(which returns the App Router's router instance with \`push\`, \`replace\`\), \`usePathname\` \(to get current path\), \`useSearchParams\` \(to get query string\), and \`useParams\` \(to get dynamic route segments\). The fix is to replace \`import \{ useRouter \} from 'next/router'\` with \`import \{ useRouter, usePathname, useSearchParams \} from 'next/navigation'\` and adjust the code accordingly \(e.g., router.query becomes useSearchParams or useParams\).
Journey Context:
You are migrating a blog from Next.js 12 \(Pages Router\) to Next.js 14 \(App Router\). You copy the \`pages/posts/\[slug\].tsx\` file to \`app/posts/\[slug\]/page.tsx\`. You keep the existing imports, including \`import \{ useRouter \} from 'next/router'\`. Inside the component, you use \`const router = useRouter\(\)\` and \`const \{ slug \} = router.query\`. When you start the dev server and navigate to the page, you see a runtime error: 'Cannot read properties of undefined \(reading 'query'\)' or the router object is empty. You check the Next.js documentation for the App Router and realize that \`next/router\` is not used here. You find the migration guide explaining that \`useRouter\` now comes from \`next/navigation\`. You change the import, but then realize \`router.query\` doesn't exist in the new \`useRouter\` hook. You look up the new API and see you need \`useParams\` to get the route segments and \`useSearchParams\` for query strings. You refactor to \`const params = useParams\(\)\` and \`const slug = params.slug\`. The page loads correctly with access to the dynamic route parameters.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T01:28:10.727948+00:00— report_created — created