React中如何通过Footer组件链接跳转到其他组件指定ref区域?
问题描述
我在React应用里有个Footer组件,里面是指向网站不同区域的链接。我没有给每个区域做独立组件,而是每个页面一个主组件,里面包含多个子区域,比如:
- First page
- section 1
- section 2
- section 3
现在想实现点击Footer里的链接,先跳转到/firstpage路由,再自动滚动到该页面的section1。目前Footer的代码是跳转到单独路由:
<Grid item xs={12} sm={3}> <Typography variant='h6'>Golf</Typography> <List> <ListItem component={NavLink} color='text.secondary' to='/section-1' sx={{textDecoration:'none', color: 'black'}}>Section 2</ListItem> <ListItem component={NavLink} color='text.secondary' to='/section-2' sx={{textDecoration:'none', color: 'black'}}>Section 2</ListItem> </List> </Grid>
我已经在页面里用div包裹各区域,并用useRef创建了引用:
const section1 = useRef(null); const section2 = useRef(null); const scrollToSection = (elementRef: any) => { window.scrollTo({ top: elementRef.current.offsetTop - 110, behavior: 'smooth' }) } return ( <> <div ref={section1}> //code </div> <div ref={section2}> //code </div> </> )
页面顶部的导航点击时会调用scrollToSection函数(比如onClick={() => scrollToSection(section2)})来滚动到对应区域。现在想利用现有代码实现Footer链接的跳转+滚动效果,是否可行?
解决方案
完全可以利用现有代码实现需求,分两步修改:
1. 修改Footer中的NavLink链接
把Footer里的to属性改成带哈希参数的路由,比如要跳转到First page的section1,就写成:
<ListItem component={NavLink} color='text.secondary' to='/firstpage#section1' sx={{textDecoration:'none', color: 'black'}}>Section 1</ListItem> <ListItem component={NavLink} color='text.secondary' to='/firstpage#section2' sx={{textDecoration:'none', color: 'black'}}>Section 2</ListItem>
2. 在FirstPage组件中监听路由哈希变化
在FirstPage组件里,引入useLocation钩子,用useEffect监听路由的哈希值变化,一旦检测到对应哈希,就调用你已有的scrollToSection函数:
import { useEffect, useRef } from 'react'; import { useLocation } from 'react-router-dom'; const FirstPage = () => { const section1 = useRef(null); const section2 = useRef(null); const location = useLocation(); const scrollToSection = (elementRef: any) => { // 增加安全判断,避免组件未挂载时调用报错 if (!elementRef.current) return; window.scrollTo({ top: elementRef.current.offsetTop - 110, behavior: 'smooth' }); }; useEffect(() => { // 组件挂载或路由哈希变化时触发滚动 const targetSection = location.hash.slice(1); // 移除开头的#号 switch(targetSection) { case 'section1': scrollToSection(section1); break; case 'section2': scrollToSection(section2); break; default: break; } }, [location.hash]); return ( <> {/* 给每个section的div加上对应id,作为浏览器默认滚动的 fallback */} <div ref={section1} id="section1"> // section1代码 </div> <div ref={section2} id="section2"> // section2代码 </div> </> ); }; export default FirstPage;
关键说明
- 给section的div添加
id属性,和哈希值一一对应,即使自定义滚动逻辑未触发,浏览器也能自动定位到对应区域; - 在
scrollToSection中增加安全判断,避免组件未完全挂载时elementRef.current为null导致的报错; - 完全复用了你已有的滚动逻辑,不需要新增额外工具或组件,改动成本极低。
内容的提问来源于stack exchange,提问作者Danny Jebb
相关产品推荐
相关产品推荐

