useRef+Context API实现滚动跳转:About组件报错失效求助
问题分析与修复方案
错误原因
你当前的代码存在两个核心问题:
- 重复渲染Navbar:About和Contact组件内部都各自渲染了Navbar,导致页面会出现多个导航栏,同时每个Navbar仅被当前组件的Context包裹。比如Contact组件中的Navbar只能获取
ContactProvider的值,无法访问AboutMeProvider,因此点击About按钮时aboutMeRef为undefined,触发Cannot read properties of undefined (reading 'current')错误。 - Context作用域不匹配:每个组件的Context仅覆盖自身内部的Navbar,全局场景下(比如Home页面单独渲染Navbar),两个Context都未提供,会导致所有滚动操作报错。
修复方案:全局Navbar + 父组件统一管理Ref
将Navbar提升为全局组件,在父组件中统一创建滚动所需的Ref,并直接将滚动逻辑传递给Navbar,无需使用Context,逻辑更简洁且避免作用域问题。
1. 父组件(App.js)重构
import React, { useRef } from 'react'; import About from './components/About'; import Contact from './components/Contact'; import Navbar from './components/Navbar'; function App() { // 创建两个Ref,分别绑定到About和Contact组件容器 const aboutMeRef = useRef(null); const contactRef = useRef(null); // 定义滚动函数,实现平滑滚动 const scrollToAbout = () => { aboutMeRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }); }; const scrollToContact = () => { contactRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }); }; return ( <div> {/* 全局Navbar,传递滚动回调 */} <Navbar onAboutClick={scrollToAbout} onContactClick={scrollToContact} /> {/* About组件容器绑定Ref */} <div ref={aboutMeRef} className="pt-5"> <About /> </div> {/* Contact组件容器绑定Ref */} <div ref={contactRef} className="pt-5"> <Contact /> </div> </div> ); } export default App;
2. 清理About.js代码
移除内部的Navbar、Context定义及多余Ref:
import React from "react"; import { useWindowScroll } from "react-use"; import second from "../images/second.jpg"; import "bootstrap-icons/font/bootstrap-icons.css"; import instagram from "../images/New folder/png/Instagram.png"; import github from "../images/New folder/png/github.png"; import Linkedin from "../images/New folder/png/Linkedin.png"; export default function About() { return ( <> <div className="h1 text-center mt-4 text-name about-heading">About Me</div> <hr className="hr hr-blurry" /> <div className="row about-main mt-4"> <div className="col aboutCol1 text-center"> <div className="about-secondCard px-4"> <img className="about-secondImg" src={second} alt="profile" /> </div> </div> <div className="col wannaKnow-main w-75 px-4"> <div className="h1 text-left mt-4 col2-text row">Wanna Know Me ?</div> <hr className="hr hr-blurry" /> <div className="rowe text-left mt-3 col2-sentence"> My name is Manglesh Kumar Born in Gorakhpur. I'm doing my graduation of B. Tech Computer Science and Engineering from Kanpur. I am a confident patient and a quick learner. </div> <a href="/" className="row knowMore btn btn-lg mt-4 active" role="button" aria-pressed="true">Know More</a> </div> </div> </> ); }
3. 清理Contact.js代码
移除内部的Navbar、Context定义及多余Ref:
import React from 'react' import { useWindowScroll } from 'react-use'; export default function Contact() { return ( <> <div className="h1 text-left p-2 col2-text row">Get in Touch</div> <hr className="hr hr-blurry" /> <form> <div className="mb-3"> <label htmlFor="exampleInputEmail1" className="form-label">Name</label> <input type="text" className="form-control" /> </div> <div className="mb-3"> <label htmlFor="exampleInputEmail1" className="form-label">E-mail</label> <input type="email" className="form-control" /> </div> <div className="mb-3"> <label htmlFor="exampleInputEmail1" className="form-label">Number</label> <input type="text" className="form-control" /> </div> <div className="mb-3"> <label htmlFor="exampleFormControlTextarea1" className="form-label"> Write Your Message here </label> <textarea className="form-control" id="exampleFormControlTextarea1" rows="3"></textarea> </div> <button type="submit" className="btn btn-primary">Submit</button> </form> </> ) }
4. 重构Navbar.js
接收父组件传递的滚动回调,移除Context相关代码:
import React from 'react' export default function Navbar({ onAboutClick, onContactClick }) { return ( <> <nav className="navbar-css-op navbar navbar-expand-lg bg-light fixed-top"> <div className="container-fluid"> <a className="navbar-brand text-dark" href="/">Manglesh</a> <button className="navbar-toggler bg-light" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation"> <span className="navbar-toggler-icon"></span> </button> <div className="collapse navbar-collapse" id="navbarTogglerDemo02"> <ul className="navbar-nav me-auto mb-2 mb-lg-0"> <li className="nav-item"> <a className="nav-link active text-dark" aria-current="page" href="/">Home</a> </li> <li className="nav-item"> <div onClick={onAboutClick} className="nav-link active text-dark">About</div> </li> <li className="nav-item"> <div onClick={onContactClick} className="nav-link active text-dark">Contacts</div> </li> </ul> </div> </div> </nav> </> ) }
优化说明
- 平滑滚动:通过
scrollIntoView的behavior: 'smooth'参数实现流畅的滚动效果。 - 避免内容遮挡:给组件容器添加
pt-5类(或自定义padding),防止固定导航栏遮挡组件内容。 - 健壮性提升:使用可选链操作符
?.,即使组件未挂载也不会触发报错。
内容的提问来源于stack exchange,提问作者nobody
相关产品推荐
相关产品推荐

