Next.js 13+:SSR与客户端组件中实现导航激活链接的方法
Next.js 13+ 兼容SSR的导航激活链接实现方案
问题根源
之前的方案中,将全局RootLayout设为客户端组件并通过window.location.pathname传递路径,存在两个核心问题:
- 客户端路由跳转(通过
<Link>)时,window.location不会触发组件重渲染,导致激活状态无法实时更新,仅页面刷新后生效 - 全局布局转为客户端组件会失去部分SSR优势,没必要将整个布局客户端化
最优解决方案:客户端组件+usePathname钩子
将Header组件单独设为客户端组件,使用Next.js 13+官方提供的usePathname钩子获取当前路径,既保留RootLayout的SSR能力,又能实时响应客户端路由变化。
1. 修改Header组件为客户端组件
'use client'; import { usePathname } from 'next/navigation'; import Link from 'next/link'; import styles from './Header.module.css'; // 自定义路由配置,根据实际项目调整 const URL = [ { path: '/', name: '首页' }, { path: '/about', name: '关于我们' }, { path: '/products', name: '产品列表' }, ]; export default function Header() { const pathname = usePathname(); return ( <nav className={styles.navigation}> <ul> {URL.map(route => ( <li key={route.path}> <Link className={route.path === pathname ? styles.highlighted : ''} href={route.path} > {route.name} </Link> </li> ))} </ul> </nav> ); }
2. 恢复RootLayout为服务器组件
移除RootLayout中的'use client'指令,保持其SSR特性,直接引入Header组件即可:
import * as React from 'react'; import { Footer, Header, Sidebar } from '../components'; import '../styles/globals.css'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html> <body> <div className='wrapper'> <Header /> {/* 无需传递pathname,Header内部自动获取 */} <Sidebar /> {children} <Footer /> </div> </body> </html> ); }
方案说明
usePathname是Next.js专为app router设计的客户端钩子,会自动监听客户端路由变化,实时更新当前路径,确保激活状态同步- RootLayout保持服务器组件,保证页面初始渲染的SSR性能和SEO友好性
- 仅将需要交互的Header转为客户端组件,遵循Next.js的"渐进式客户端组件"最佳实践
备选方案:服务器组件中获取路径(静态场景)
如果你的页面都是静态渲染,无需动态客户端导航,可以在服务器组件中通过headers()获取初始路径,但注意该路径仅在服务器渲染时生效,客户端导航时不会更新:
import { headers } from 'next/headers'; export default function StaticHeader() { const headersList = headers(); const pathname = headersList.get('x-nextjs-pathname') || '/'; return ( <nav className={styles.navigation}> <ul> {URL.map(route => ( <li key={route.path}> <Link className={route.path === pathname ? styles.highlighted : ''} href={route.path} > {route.name} </Link> </li> ))} </ul> </nav> ); }
内容的提问来源于stack exchange,提问作者Animus
相关产品推荐
相关产品推荐

