先给结论:如果你在 Next.js App Router 项目中遭遇“NextRouter was not mounted”报错,绝大多数情况下是导入路径使用不当所致。正确的解决方式是使用 next/navigation 而非 next/router 来导入 useRouter,同时务必在组件顶部显式添加 'use client' 指令。虽然问题本身看似简单,但其背后反映了 App Router 与 Pages Router 在路由架构设计上的本质区别。

Next.js 13+ 引入的 App Router 与传统的 Pages Router 在路由 API 层面完全是两套不同体系:next/router 基于旧版 Router 实例,仅适用于 Pages Router;而在 App Router 环境下,所有路由能力均由 next/navigation 统一提供,涵盖 useRouter、useSearchParams、redirect 和 notFound 等核心接口。
因此,你代码中报错的根本原因非常清晰:
- ❌ 错误写法:
import { useRouter } from 'next/router'—— 该写法在 App Router 中无效,导致路由无法正常挂载; - ✅ 正确写法:
import { useRouter } from 'next/navigation'—— 这是 App Router 官方推荐的客户端路由 Hook 导入方式。
除此之外,还有几个关键要点值得特别留意:
✅ 正确用法示例(适配 App Router)
'use client';import { useRouter, useSearchParams } from 'next/navigation';import { useEffect, useState } from 'react';export default function NFTDetails() { const router = useRouter(); const searchParams = useSearchParams(); // 推荐用于读取 query 参数 const [nft, setNft] = useState>({}); // 方案一:使用 useSearchParams(推荐,无需依赖路由就绪状态) useEffect(() => { const data = Object.fromEntries(searchParams.entries()); setNft(data); }, [searchParams]); // 方案二:若需监听路由变化或执行导航,可结合 useRouter.push() // router.push('/nft-details?tokenId=123'); return (
NFT Details
{JSON.stringify(nft, null, 2)} );}
