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

React页面跳转后自动滚动到指定区块问题求助

React Router跳转后自动滚动到指定区块的解决方案

你的现有代码问题分析

你之前在App.jsx里用useEffect设置window.location.hash的思路没问题,但失效的核心原因是:

  • 路由跳转后,目标页面的DOM还没完全渲染完成,此时设置hash找不到对应元素;
  • 过早执行setSec(null)清空状态,导致后续目标页面无法读取到区块名称;
  • 全局状态的更新时机和组件渲染时机不匹配,App的useEffect先于目标页面组件执行。

方案一:用URL参数/Hash传递区块名(推荐)

这种方式不需要全局状态,依赖路由本身的参数传递,更可靠且符合路由设计逻辑。

1. 跳转页面传递Hash参数

import { useNavigate } from 'react-router-dom';

function SourcePage() {
  const navigate = useNavigate();

  const goToSection2 = () => {
    // 直接把区块ID作为Hash拼到目标路由后
    navigate('/target-page#section-2');
  };

  return <button onClick={goToSection2}>跳转到Section 2</button>;
}

2. 目标页面监听Hash并滚动

import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

function TargetPage() {
  const location = useLocation();

  useEffect(() => {
    // 提取Hash(去掉开头的#)
    const targetSection = location.hash.slice(1);
    if (!targetSection) return;

    // 找到对应DOM元素并滚动
    const element = document.getElementById(targetSection);
    if (element) {
      element.scrollIntoView({ 
        behavior: 'smooth', // 平滑滚动
        block: 'start' // 元素顶部对齐视口
      });
    }
  }, [location]); // 监听路由变化

  return (
    <div>
      <div style={{ height: '1000px' }}>顶部占位内容</div>
      {/* 给目标区块设置ID,和传递的Hash一致 */}
      <section id="section-2">这是Section 2的内容</section>
      <div style={{ height: '1000px' }}>底部占位内容</div>
    </div>
  );
}

方案二:用全局状态传递区块名(适配你的现有逻辑)

如果必须用全局状态传递,需要确保目标页面DOM渲染完成后再执行滚动:

1. 全局状态上下文(替代你的useState)

// SectionContext.js
import { createContext, useState, useContext } from 'react';

const SectionContext = createContext();

export function SectionProvider({ children }) {
  const [targetSection, setTargetSection] = useState(null);
  return (
    <SectionContext.Provider value={{ targetSection, setTargetSection }}>
      {children}
    </SectionContext.Provider>
  );
}

export function useSection() {
  return useContext(SectionContext);
}

2. 跳转页面更新全局状态

import { useNavigate } from 'react-router-dom';
import { useSection } from './SectionContext';

function SourcePage() {
  const navigate = useNavigate();
  const { setTargetSection } = useSection();

  const goToSection2 = () => {
    setTargetSection('section-2');
    navigate('/target-page');
  };

  return <button onClick={goToSection2}>跳转到Section 2</button>;
}

3. 目标页面监听状态并滚动

import { useEffect, useRef } from 'react';
import { useSection } from './SectionContext';

function TargetPage() {
  const { targetSection, setTargetSection } = useSection();
  // 用useRef绑定目标区块
  const section2Ref = useRef(null);

  useEffect(() => {
    if (!targetSection || targetSection !== 'section-2') return;

    // 用requestAnimationFrame确保DOM渲染完成后再滚动
    requestAnimationFrame(() => {
      section2Ref.current?.scrollIntoView({ behavior: 'smooth' });
      // 滚动完成后清空状态,避免下次进入页面重复触发
      setTargetSection(null);
    });
  }, [targetSection, setTargetSection]);

  return (
    <div>
      <div style={{ height: '1000px' }}>顶部占位内容</div>
      <section ref={section2Ref}>这是Section 2的内容</section>
      <div style={{ height: '1000px' }}>底部占位内容</div>
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 06:33:21