Inertia React点击Link路由跳转前执行函数修复滚动锁定问题
问题根因
- 自定义
NavLink组件未接收、透传onClick等外部传入的属性,你在NavBar中给NavLink绑定的hideNav事件根本没有挂载到实际的Inertia Link元素上,点击时完全不会执行。 hideNav方法中错误调用了e.preventDefault(),会直接拦截Link组件的默认路由跳转逻辑,就算事件绑定成功也会导致路由无法正常跳转。- 仅靠点击事件做状态清理没有兜底逻辑,遇到浏览器前进后退、代码主动触发跳转等场景时,仍会残留
overflow-hidden类导致页面滚动被锁。 NavLink中无意义引入了react-router-dom的useNavigate方法,你的项目完全由Inertia接管路由,该引用属于冗余代码。
修复方案
1. 改造NavLink组件,透传所有属性
修改NavLink.js,删除冗余的react-router-dom引入,将外部传入的onClick等属性透传给底层Inertia Link组件:
// NavLink.js import React from "react"; import { Link } from "@inertiajs/inertia-react"; export default function NavLink({ href, active, children, className = "", ...rest }) { return ( <Link href={href} className={ (active ? "inline-flex items-center px-1 pt-1 border-b-2 border-[#ed8686] text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-[#E05D5D] transition duration-150 ease-in-out dark:text-gray-400" : "inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out dark:text-gray-300 dark:hover:text-gray-500 dark:hover:border-gray-300 dark:focus:outline-none dark:focus:text-gray-500 dark:focus:border-gray-300") + ` ${className}` } {...rest} > {children} </Link> ); }
2. 修正导航开关方法,移除错误的事件拦截
修改NavBar.js中的toggleNav和hideNav方法,删除不必要的e.preventDefault()调用,避免拦截Link的默认跳转行为,同时增加空值判断避免ref未挂载时报错:
const toggleNav = () => { const navBar = mobileNavRef.current; if (!navBar) return; navBar.classList.toggle("active"); document.body.classList.toggle("overflow-hidden"); }; const hideNav = () => { const navBar = mobileNavRef.current; if (navBar) navBar.classList.remove("active"); document.body.classList.remove("overflow-hidden"); };
3. 增加路由跳转全局兜底清理
在NavBar中引入Inertia,监听全局路由跳转事件,无论什么原因触发的页面跳转,都自动关闭移动端导航、移除滚动锁,彻底避免滚动被锁的问题:
首先在NavBar.js的导入部分添加:
import { Inertia } from "@inertiajs/inertia";
然后在组件中添加对应的事件监听useEffect:
useEffect(() => { const clearNavState = () => hideNav(); Inertia.on("navigate", clearNavState); return () => Inertia.off("navigate", clearNavState); }, []);
(可选)优化原有滚动监听逻辑
你代码中标注了滚动监听导致过多重渲染的问题,可以把原来依赖scrollTop state的逻辑改成直接操作DOM class,不需要把滚动位置存在state中触发组件重渲染:
useEffect(() => { const navBar = navRef.current; if (!navBar) return; const handleScroll = () => { const currentScrollTop = document.documentElement.scrollTop; navBar.classList.toggle("scrolled", currentScrollTop >= 80); }; window.addEventListener("scroll", handleScroll, { passive: true }); handleScroll(); return () => window.removeEventListener("scroll", handleScroll); }, []);
修改后滚动时不会触发整个NavBar组件重渲染,性能更好。
内容的提问来源于stack exchange,提问作者Raahim Fareed
相关产品推荐
相关产品推荐

