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

React中如何路由至首页后滚动到指定组件?

问题解决:React路由跳转后react-scroll无法找到目标元素

问题根源

你调用await navigate("/")后立即执行scroller.scrollTo,但navigate的Promise完成仅代表路由状态更新,Home组件还未完成渲染挂载,此时DOM中还没有目标元素,所以会报target Element not found错误。

解决方案

方案一:通过路由状态传递滚动目标(推荐)

这种方式把滚动逻辑放到Home组件中,更符合组件职责分离:

  1. 修改Navbar中的goToPageAndScroll函数,通过路由state传递滚动目标:
const goToPageAndScroll = (selector) => {
  // 把要滚动的目标存入路由state
  navigate("/", { state: { scrollTo: selector } });
};
  1. 在Home组件中监听路由state,完成渲染后执行滚动:
import React, { useState, useEffect } from 'react'
import { useLocation } from 'react-router-dom';
import * as Scroll from 'react-scroll';
// 其他组件导入...

const Home = () => {
  const [playState, setPlayState] = useState(false);
  const location = useLocation();
  const scroller = Scroll.scroller;

  useEffect(() => {
    const { scrollTo } = location.state || {};
    if (scrollTo) {
      // 用requestAnimationFrame确保DOM已渲染完成
      requestAnimationFrame(() => {
        scroller.scrollTo(scrollTo, {
          duration: 500,
          smooth: true,
          offset: -75,
          spy: true
        });
      });
    }
  }, [location.state, scroller]);

  // 原Home组件的JSX内容...
};

export default Home

方案二:在Navbar中监听路由变化

如果不想修改Home组件,可以在Navbar中等待路由跳转完成后再执行滚动:

  1. 在Navbar中添加状态存储滚动目标:
import { useState, useEffect } from 'react';
// 其他导入...

const Navbar = () => {
  const path = useLocation().pathname;
  const location = path.split("/")[1];
  const navigate = useNavigate();
  const scroller = Scroll.scroller;
  // 存储要滚动的目标
  const [targetScroll, setTargetScroll] = useState(null);

  const goToPageAndScroll = (selector) => {
    setTargetScroll(selector);
    navigate("/");
  };

  // 监听路径变化,回到首页时执行滚动
  useEffect(() => {
    if (path === "/" && targetScroll) {
      // 用setTimeout等待组件渲染,时间可根据实际调整
      const timer = setTimeout(() => {
        scroller.scrollTo(targetScroll, {
          duration: 500,
          smooth: true,
          offset: -75,
          spy: true
        });
        setTargetScroll(null); // 重置目标,避免重复触发
      }, 100);
      return () => clearTimeout(timer);
    }
  }, [path, targetScroll, scroller]);

  // 原Navbar的JSX内容...
};

方案三:结合路由Link与URL hash

直接通过URL hash传递目标,利用浏览器原生hash特性+react-scroll处理:

  1. 修改非首页时的导航为react-router的Link:
import { Link } from 'react-router-dom';
// 非首页时的导航代码
<>
  <li><Link to="/#hero">Home</Link></li>
  <li><Link to="/#services">Services</Link></li>
  <li><Link to="/#about">About</Link></li>
  <li><Link to="/#gallery">Gallery</Link></li>
  <li><Link to="/#contact">Contact</Link></li>
</>
  1. 在Home组件中解析hash并执行滚动:
useEffect(() => {
  const hash = window.location.hash.slice(1); // 去除#号
  if (hash) {
    scroller.scrollTo(hash, {
      duration: 500,
      smooth: true,
      offset: -75,
      spy: true
    });
  }
}, []);

注意事项

  • 确保Home页面的各板块组件根元素确实设置了对应id(比如Hero组件根div的id为hero,Services为services等),检查拼写是否与传递的selector一致。
  • 如果使用setTimeout,时间不要设置太长,100ms左右足够,避免用户感知延迟。

内容的提问来源于stack exchange,提问作者LittleDTLe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:54:54