React HashRouter下页面内部锚点链接失效问题求助
React HashRouter 下锚点滚动失效解决方案
问题根源
HashRouter 的 URL 结构为 /#/路由路径,原生 <a> 标签跳转到 /#about-me 会被 React Router 识别为路由路径,导致匹配不到主页路由而显示空白;使用 <Link to="/#about-me"> 会生成双层 hash(/#/#about-me),触发页面刷新且无法正确定位。
解决方法
方法一:直接绑定滚动事件(无路由依赖)
放弃 <a>/<Link>,用普通元素绑定点击事件,直接控制滚动并同步 URL:
import { useNavigate } from 'react-router-dom'; function Navbar() { const navigate = useNavigate(); const scrollToSection = (sectionId) => { // 若当前不在主页,先跳转主页 if (!window.location.hash.includes('/')) { navigate('/', { replace: true }); setTimeout(() => triggerScroll(sectionId), 100); } else { triggerScroll(sectionId); } }; const triggerScroll = (id) => { const element = document.getElementById(id); element?.scrollIntoView({ behavior: 'smooth' }); window.location.hash = id; }; return ( <nav> <div className="nav-link" onClick={() => scrollToSection('about-me')}>About Me</div> <div className="nav-link" onClick={() => scrollToSection('projects')}>Projects</div> </nav> ); }
方法二:监听路由 hash 自动滚动
通过 React Router 的 useLocation 监听 hash 变化,自动定位到目标元素:
// Home.js import { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; function Home() { const location = useLocation(); useEffect(() => { const sectionId = location.hash.slice(1); if (sectionId) { const target = document.getElementById(sectionId); target?.scrollIntoView({ behavior: 'smooth' }); } }, [location.hash]); return ( <div> <section id="about-me">...</section> <section id="projects">...</section> </div> ); }
导航时用 navigate 传递 hash 参数:
// 导航组件中 import { useNavigate } from 'react-router-dom'; function Navbar() { const navigate = useNavigate(); return ( <nav> <button className="nav-link" onClick={() => navigate('/', { hash: 'about-me' })}>About Me</button> </nav> ); }
方法三:GitHub Pages 部署适配
若部署在仓库子路径(如 https://username.github.io/repo-name/),需给 HashRouter 设置 basename:
// index.js import { HashRouter } from 'react-router-dom'; ReactDOM.render( <HashRouter basename="/repo-name/"> <App /> </HashRouter>, document.getElementById('root') );
注意事项
- 禁止用原生
<a>标签直接跳转锚点,避免路由匹配错误。 - 跨页面跳转后滚动需加延迟(
setTimeout),确保主页 DOM 渲染完成。 - 双层 hash(
/#/#about-me)不影响功能,仅为 HashRouter 的特性表现。
内容的提问来源于stack exchange,提问作者ChristopherOjo
相关产品推荐
相关产品推荐

