React导航链接点击不跳转锚点,强制更新报错页面冻结
React Router 锚点跳转不生效问题解决
问题根源
React Router 的Link组件在跳转同路由下的锚点时,只会更新 URL 的 hash 部分,不会触发浏览器默认的锚点滚动行为——因为路由组件(这里的Home)没有重新挂载,浏览器不会自动处理锚点定位。而手动输入 URL 能正常跳转,是因为页面完整加载时,浏览器会自动识别并滚动到对应锚点。
你之前尝试的强制重渲染方案完全错误:NavBar是函数组件,不存在this上下文,所以this.setState和this.forceUpdate会直接抛出Cannot read properties of undefined错误,同时强制重渲染也不是解决锚点问题的正确方向。
正确解决方案
方案一:监听路由变化自动滚动(推荐)
在路由组件Home中监听location的变化,当 hash 改变时主动滚动到对应元素,无需修改导航栏的Link逻辑:
// Home.jsx import { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; import Container from 'react-bootstrap/Container'; import NavBar from './NavBar'; import HomeContent from './HomeContent'; import Pricing from './Pricing'; import Footer from './Footer'; function Home() { const location = useLocation(); useEffect(() => { // 提取URL中的锚点ID const targetId = location.hash.slice(1); if (targetId) { const targetElement = document.getElementById(targetId); if (targetElement) { // 平滑滚动到锚点 targetElement.scrollIntoView({ behavior: 'smooth' }); } } else { // 无锚点时滚动到页面顶部 window.scrollTo({ top: 0, behavior: 'smooth' }); } }, [location]); // 监听location变化触发执行 return ( <div> <Container fluid> <NavBar /> <HomeContent /> </Container> <Pricing /> <Footer /> </div> ); } export default Home;
方案二:修改导航栏点击事件手动处理滚动
如果不想修改Home组件,可以在NavBar中用useNavigate钩子,跳转后手动触发滚动:
// NavBar.jsx import { useNavigate } from 'react-router-dom'; import Navbar from 'react-bootstrap/Navbar'; import Container from 'react-bootstrap/Container'; import Nav from 'react-bootstrap/Nav'; import { Link } from 'react-router-dom'; function NavBar() { const navigate = useNavigate(); const handleAnchorJump = (targetPath) => { navigate(targetPath); // 延迟执行滚动,确保路由状态更新完成 setTimeout(() => { const targetId = window.location.hash.slice(1); if (targetId) { const targetElement = document.getElementById(targetId); targetElement?.scrollIntoView({ behavior: 'smooth' }); } }, 100); }; return ( <> <Navbar variant="dark" expand="lg"> <Container> <Navbar.Brand onClick={() => handleAnchorJump('/home')} as={Link} to="/home"> </Navbar.Brand> <Navbar.Toggle aria-controls="basic-navbar-nav" /> <Navbar.Collapse id="basic-navbar-nav"> <Nav className="justify-content-end flex-grow-1 pe-3"> <Nav.Link onClick={() => handleAnchorJump('/home')} as={Link} to="/home"> Home </Nav.Link> <Nav.Link onClick={() => handleAnchorJump('/home#pricing')} as={Link} to="/home#pricing"> Pricing </Nav.Link> </Nav> </Navbar.Collapse> </Container> </Navbar> </> ); } export default NavBar;
额外说明
- 移除你之前写的
handleClick函数:函数组件没有this,这类写法完全无效; - 两种方案都支持平滑滚动,若不需要可以去掉
behavior: 'smooth'参数; - 无需使用
withRouter,React Router v6 中函数组件直接用useLocation、useNavigate等钩子即可获取路由上下文。
内容的提问来源于stack exchange,提问作者Beloved
相关产品推荐
相关产品推荐

