React Router中useEffect与useLocation同步异常:滚轮导航失效问题
问题诊断与解决方案
核心问题
你遇到的是闭包捕获旧值的问题:当从/work路由点击进入嵌套路由时,ContextProvider中绑定的handleNavigation函数仍然引用着路由切换前的location.pathname(也就是/work),所以location.pathname.includes('/work/')的判断不成立,滚轮导航依旧触发。而手动在地址栏输入嵌套路由时,组件会重新挂载,location是最新的嵌套路径,判断自然生效。
解决方案1:让事件处理函数依赖最新的location
用useCallback包裹handleNavigation,并将location加入依赖数组,确保路由变化时,函数能重新创建并捕获最新的路径值:
import { useNavigate, useLocation } from 'react-router-dom'; import { useEffect, useCallback } from 'react'; function ContextProvider({ children }) { const navigate = useNavigate(); const location = useLocation(); const routes = ['/main', '/skills', '/aboutme', '/work']; // 用useCallback包裹,确保路由变化时函数更新 const handleNavigation = useCallback((e) => { // 用startsWith更精准,避免误判类似/mywork/的路径 if (location.pathname.startsWith('/work/')) { return; } const currentIndex = routes.findIndex(route => route === location.pathname); let newIndex = currentIndex; newIndex = e.deltaY > 0 ? (currentIndex + 1) % routes.length : (currentIndex - 1 + routes.length) % routes.length; navigate(routes[newIndex]); }, [location, navigate, routes]); useEffect(() => { window.addEventListener('wheel', handleNavigation); return () => window.removeEventListener('wheel', handleNavigation); }, [handleNavigation]); // 依赖更新后的handleNavigation return <>{children}</>; }
解决方案2:实时获取当前路径(更简洁)
直接在事件触发时读取window.location.pathname,完全避开闭包带来的旧值问题:
const handleNavigation = (e) => { const currentPath = window.location.pathname; if (currentPath.startsWith('/work/')) { return; } const currentIndex = routes.findIndex(route => route === currentPath); let newIndex = currentIndex; newIndex = e.deltaY > 0 ? (currentIndex + 1) % routes.length : (currentIndex - 1 + routes.length) % routes.length; navigate(routes[newIndex]); };
关键说明
- 之前调整useEffect依赖无效,是因为你只更新了useEffect的依赖,但
handleNavigation函数本身没有重新创建,内部依然引用旧的location值。 - 用
startsWith('/work/')替代includes('/work/'),能避免误判包含work字段的非嵌套路由(比如/my-work)。
内容的提问来源于stack exchange,提问作者jacksonmendoza
相关产品推荐
相关产品推荐

