同时使用react-router-dom与react-scroll实现导航栏遇问题求助
解决React混合导航(页面内滚动+路由跳转)的两个问题
问题1:路由跳转后,页面内滚动链接仍保持激活状态
问题根源是react-scroll的Link组件激活状态仅基于当前页面滚动位置判断,路由切换到新页面后不会自动重置。
解决思路
通过监听路由变化,在离开首页时手动清空页面内滚动链接的激活状态,同时自定义激活判断逻辑,仅在首页且对应区块处于可视范围时标记激活。
示例代码:
import { useLocation, Link as RouterLink } from "react-router-dom"; import { useEffect, useState } from "react"; import { Link as ScrollLink } from "react-scroll"; function Navbar() { const location = useLocation(); const [activeScrollId, setActiveScrollId] = useState("home"); // 路由离开首页时重置激活状态 useEffect(() => { if (location.pathname !== "/") { setActiveScrollId(""); } }, [location.pathname]); return ( <nav> <ScrollLink to="home" spy={true} smooth={true} activeClass="active" isActive={() => location.pathname === "/" && activeScrollId === "home"} onClick={() => setActiveScrollId("home")} > Home </ScrollLink> <ScrollLink to="about" spy={true} smooth={true} activeClass="active" isActive={() => location.pathname === "/" && activeScrollId === "about"} onClick={() => setActiveScrollId("about")} > About </ScrollLink> <ScrollLink to="contact" spy={true} smooth={true} activeClass="active" isActive={() => location.pathname === "/" && activeScrollId === "contact"} onClick={() => setActiveScrollId("contact")} > Contact </ScrollLink> <RouterLink to="/new-page">New Page</RouterLink> </nav> ); }
问题2:从新页面返回时出现“target Element not found”错误
问题原因是从新页面返回首页时,react-scroll会立即尝试滚动到之前的目标,但此时首页DOM元素尚未完全渲染,导致找不到目标节点。
解决思路
监听路由回到首页的时机,等待DOM元素加载完成后再执行滚动逻辑;同时在点击滚动链接时,将目标区块ID存入路由状态,返回时读取该状态进行滚动。
示例代码(首页组件):
import { useEffect, useRef } from "react"; import { useLocation } from "react-router-dom"; import { scroller } from "react-scroll"; function HomePage() { const homeRef = useRef(null); const aboutRef = useRef(null); const contactRef = useRef(null); const location = useLocation(); useEffect(() => { if (location.pathname === "/") { // 读取路由状态中保存的滚动目标 const targetId = location.state?.scrollTarget || "home"; const targetRef = { home: homeRef, about: aboutRef, contact: contactRef }[targetId]; // 确认元素存在后再执行滚动 if (targetRef.current) { scroller.scrollTo(targetId, { smooth: true, spy: true }); } } }, [location.pathname]); return ( <div> <div ref={homeRef} id="home">Home Section</div> <div ref={aboutRef} id="about">About Section</div> <div ref={contactRef} id="contact">Contact Section</div> </div> ); }
修改导航栏滚动链接的点击逻辑,保存目标到路由状态:
<ScrollLink to="home" spy={true} smooth={true} onClick={() => { setActiveScrollId("home"); // 保存滚动目标到路由状态 window.history.replaceState({ scrollTarget: "home" }, ""); }} > Home </ScrollLink>
内容的提问来源于stack exchange,提问作者Jonas Bjørn Pedersen
相关产品推荐
相关产品推荐

