
Next.js 13 使用 App Router 时,点击 却触发整页重载而非客户端导航,通常因错误导入了第三方 Link(如 MUI 的 Link)而非 Next.js 原生 next/link,导致丢失声明式导航能力。
next.js 13 使用 app router 时,点击 `` 却触发整页重载而非客户端导航,通常因错误导入了第三方 `link`(如 mui 的 `link`)而非 next.js 原生 `next/link`,导致丢失声明式导航能力。
在 Next.js 13 的 App Router 架构中,真正的“单页应用(SPA)式”路由切换依赖于框架提供的 组件——它通过拦截原生 标签行为、调用 next/navigation 内部的 prefetch 和 navigate 机制,实现无刷新的客户端过渡(Client-Side Navigation)。一旦使用了非 Next.js 提供的 (例如 Material-UI、Chakra UI 或自定义封装的链接组件),该组件仅渲染为普通 标签,浏览器会执行完整页面跳转(Full Page Reload),彻底绕过 App Router 的导航系统。
? 快速诊断方法:
检查你的 SideBar 组件中 Link 的导入路径:
// ❌ 错误:使用 MUI Link(或其他 UI 库 Link)
import { Link } from '@mui/material';
// ✅ 正确:必须使用 Next.js 官方 Link
import Link from 'next/link';
⚠️ 注意:next/link 是默认导出(default export),不可解构导入;而 MUI 等库的 Link 是命名导出(named export),二者语法兼容但语义完全不同。
? 修复步骤:
-
在 SideBar.tsx(或相关导航组件)中,将所有 Link 导入替换为:
import Link from 'next/link';
确保 Link 组件未被额外包裹或透传 props 导致行为降级(例如:避免 asChild、forwardRef 不当使用,或意外添加 target="_blank"/onClick 阻断默认行为);
-
若需保留 UI 库样式(如 MUI 的 Link 外观),可组合使用:
import Link from 'next/link'; import { Link as MuiLink } from '@mui/material'; // 用 Next.js Link 包裹 MUI Link,保持导航能力 <link href="%7Bchild.path%7D" passhref legacybehavior><muilink>{child.title}</muilink>⚠️ passHref + legacyBehavior 仅在 Pages Router 中必需;App Router 中推荐直接使用 next/link 并通过 className 或 sx 注入样式,更简洁可靠。
✅ 附加验证建议:
- 打开浏览器开发者工具 → Network 标签页 → 点击导航链接 → 观察是否发起 document 类型请求(整页加载)还是 xhr/fetch 类请求(客户端导航);
- 检查控制台是否有警告:Warning: Prop 'href' did not match. —— 这往往暗示服务端渲染(SSR)与客户端 hydration 时 Link 行为不一致,根源仍是组件误用。
? 延伸提醒:
- 所有用于导航的 标签,若未包裹 next/link,均会触发硬跳转;
- useRouter() 的 push() 方法虽可编程导航,但应避免在事件处理器中滥用(如 onClick={() => router.push(...)}),优先使用声明式 以保障 prefetch 和 SEO 友好性;
- 若项目已集成 RecoilRoot 等状态容器,请确认其位于 layout.tsx 的稳定层级(如 下唯一根节点),避免因布局组件重渲染导致 Link 实例重建——但这属于次要因素,首要排查永远是 Link 的导入来源。
遵循以上修正后,路由切换将恢复为平滑的客户端导航,Layout 持久化、状态保留、Streaming 渲染等 App Router 核心优势方可真正生效。











