React仅首页导航栏滚动变色异常:路由切换后仍变化
路由切换后Header导航栏样式异常问题
组件代码
React状态与逻辑部分
const [small, setSmall] = useState(false) console.log(window.location.pathname) console.log(window.location.pathname === '/') useEffect(() => { if (typeof window !== "undefined") { if(window.location.pathname === '/'){ window.addEventListener("scroll", () => setSmall(window.scrollY > 640), ); } } }, []);
HTML部分
<nav className={`padding-280px ${ small ? "colorful" : "transparent"}`}
问题描述
处于非根路由(window.location.pathname !== '/')时,控制台已确认路径不等于根路径,但Header导航栏仍会随着滚动改变样式(small状态被修改)。
解决建议
重置状态+监听路由变化+清理监听
原代码只在组件挂载时判断路径并添加滚动监听,路由切换后组件不会重新挂载,旧的监听仍在运行,会持续修改small状态。可以借助React Router的useLocation钩子监听路由变化:import { useLocation } from 'react-router-dom'; const location = useLocation(); const [small, setSmall] = useState(false); useEffect(() => { const handleScroll = () => setSmall(window.scrollY > 640); if (typeof window !== "undefined") { // 先移除旧监听,避免重复绑定 window.removeEventListener("scroll", handleScroll); if (location.pathname === '/') { window.addEventListener("scroll", handleScroll); // 切回根路由时,同步当前滚动位置的状态 setSmall(window.scrollY > 640); } else { // 非根路由直接重置为透明样式状态 setSmall(false); } } // 组件卸载时清理监听 return () => { if (typeof window !== "undefined") { window.removeEventListener("scroll", handleScroll); } }; }, [location.pathname]); // 路由变化时重新执行副作用直接在渲染层判断路径与滚动状态
不需要依赖small状态,直接在className中结合当前路径和滚动值判断样式,从根源避免状态异常:const [scrollY, setScrollY] = useState(0); useEffect(() => { const handleScroll = () => setScrollY(window.scrollY); window.addEventListener("scroll", handleScroll); return () => window.removeEventListener("scroll", handleScroll); }, []); <nav className={`padding-280px ${window.location.pathname === '/' && scrollY > 640 ? "colorful" : "transparent"}`}核心注意点
任何时候添加全局事件监听,都要在组件卸载或相关依赖变化时移除监听,否则会导致内存泄漏和状态不受控的问题。
内容的提问来源于stack exchange,提问作者Y U K I M U R A
相关产品推荐
相关产品推荐

