Next.js路由跳转时Navbar组件高亮状态延迟更新问题求解
问题根因
- 你定义的
navigation数组是组件外部的全局常量,直接在useEffect中修改它的current属性不会触发React组件的重渲染,界面自然不会同步更新。你看到的「延迟更新」本质是:路由跳转时修改了全局常量的值,但要等下一次组件因为其他原因重渲染时,才会读取上一次修改后的值,所以永远慢一步。 useEffect依赖项配置错误:监听整个router引用对象不会精准触发回调,应该监听路由的实际变化值比如router.route。- 没有使用React状态管理激活项,不符合React的响应式更新逻辑。
修复方案(推荐:无需useEffect,更简洁)
直接在渲染菜单项时实时判断当前路由是否匹配,不需要额外维护current状态和副作用:
import Link from "next/link"; import { useRouter } from "next/router"; function classNames(...classes) { return classes.filter(Boolean).join(" "); } // 导航配置去掉冗余的current字段 const navigation = [ { name: "page1", href: "/" }, { name: "page2", href: "/page2" }, { name: "page3", href: "/page3" }, ]; export default function Navbar() { const router = useRouter(); return ( <div> <div> {navigation.map((item) => { // 渲染时实时判断是否为当前激活页 const isCurrent = router.route === item.href; return ( <Link href={item.href} key={item.name}> <a className={classNames( isCurrent ? "border-indigo-500 text-gray-900" : "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700", "inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium" )} aria-current={isCurrent ? "page" : undefined} > {item.name} </a> </Link> ); })} </div> </div> ); }
可选方案:用状态管理激活项
如果你的业务场景需要单独维护激活状态,可以用useState配合useEffect实现:
import Link from "next/link"; import { useRouter } from "next/router"; import { useEffect, useState } from "react"; function classNames(...classes) { return classes.filter(Boolean).join(" "); } const navigation = [ { name: "page1", href: "/" }, { name: "page2", href: "/page2" }, { name: "page3", href: "/page3" }, ]; export default function Navbar() { const router = useRouter(); // 用状态存当前激活的路径 const [currentPath, setCurrentPath] = useState(router.route); // 路由变化时更新状态,触发重渲染 useEffect(() => { setCurrentPath(router.route); }, [router.route]); // 依赖项指定为路由字符串,精准触发 return ( <div> <div> {navigation.map((item) => { const isCurrent = currentPath === item.href; return ( <Link href={item.href} key={item.name}> <a className={classNames( isCurrent ? "border-indigo-500 text-gray-900" : "border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700", "inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium" )} aria-current={isCurrent ? "page" : undefined} > {item.name} </a> </Link> ); })} </div> </div> ); }
内容的提问来源于stack exchange,提问作者Brenton Beltrami
相关产品推荐
相关产品推荐

