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

同时使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 22:20:31