You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 16:57:23