React TS中父组件Ref传子组件时出现.current不存在的TS错误
父组件Ref传递给子组件的TypeScript类型问题及解决示例
把App组件的mainContainer ref传给Navbar子组件后,访问mainContainer.current触发TypeScript错误:
Property 'current' does not exist on type '((instance: unknown) => void) | MutableRefObject'.
Property 'current' does not exist on type '(instance: unknown) => void'.ts(2339)
实际属性存在且能正常访问,但类型识别存在问题。
问题原因
React的Ref类型包含两种形式:MutableRefObject(即useRef创建的带current属性的对象)和回调函数式ref。forwardRef的第二个参数ref默认类型为Ref<T> | undefined,TypeScript无法确定传入的ref一定是带current的对象,因此触发报错。
方案1:通过Props传递父组件Ref(推荐)
forwardRef的设计初衷是子组件向父组件暴露自身DOM节点/组件实例,反向传递父组件的ref更适合用普通props,语义清晰且类型易处理。
父组件(App.tsx)
import Navbar from "./components/Navbar.tsx" import app from "./App.module.css" import { useRef } from "react" function App() { const mainContainer = useRef<HTMLDivElement | null>(null); return ( <> <div id={app.mainContainer} ref={mainContainer}> <button className="nav-btn" id="open-nav-btn">Menu</button> {/* 通过props传递父组件ref */} <Navbar mainContainerRef={mainContainer} /> </div> </> ) } export default App
子组件(Navbar.tsx)
import "./navbar.css" import { gsap } from "gsap"; import { useGSAP } from "@gsap/react"; import { useRef } from "react"; import { ExpoScaleEase } from "gsap/EasePack"; gsap.registerPlugin(useGSAP, ExpoScaleEase); // 定义Props类型,明确ref的类型 type NavbarProps = { mainContainerRef: React.MutableRefObject<HTMLDivElement | null>; }; const Navbar = ({ mainContainerRef }: NavbarProps) => { const navContainer = useRef<HTMLDivElement>(null); const { contextSafe } = useGSAP({ scope: navContainer }); const closeNav = contextSafe(() => { const duration: number = 0.4; // 类型明确,可安全访问current if (mainContainerRef.current && navContainer.current) { gsap.set( mainContainerRef.current, { overflow: "auto" } ); gsap.to( navContainer.current, { opacity: 0, ease: "power2.in", duration } ); gsap.set( navContainer.current, { clipPath: "inset(100% 0% 0% 0%)", delay: duration } ); gsap.set( navContainer.current, { display: "none", delay: duration } ); } }); return ( <div id="nav-container" ref={navContainer}> <button className="nav-btn" id="close-nav-btn" onClick={closeNav}>Close</button> <div className="nav-wrapper"> <nav> <ul className="nav-pages"> <li>HOME</li> <li>ABOUT</li> <li>CONTACT</li> <li>PROJECTS</li> </ul> <hr /> <ul className="nav-socials"> <li>Instagram</li> <li>Linkedin</li> <li>Github</li> </ul> </nav> <p>Mirko Bellopede <br /> Full stack web developer Portfolio 2024 ©</p> </div> </div> ); }; export default Navbar
方案2:使用forwardRef并明确类型(不推荐,语义不符)
如果一定要用forwardRef传递父组件的ref,需明确ref的类型并添加类型断言:
修改后的子组件(Navbar.tsx)
import "./navbar.css" import { gsap } from "gsap"; import { useGSAP } from "@gsap/react"; import { forwardRef, useRef } from "react"; import { ExpoScaleEase } from "gsap/EasePack"; gsap.registerPlugin(useGSAP, ExpoScaleEase); // 明确forwardRef的泛型类型为MutableRefObject const Navbar = forwardRef<React.MutableRefObject<HTMLDivElement | null>, {}>(function Navbar(props, ref) { const navContainer = useRef<HTMLDivElement>(null); // 类型断言,告知TS该ref为带current的对象 const mainContainer = ref as React.MutableRefObject<HTMLDivElement | null>; const { contextSafe } = useGSAP({ scope: navContainer }); const closeNav = contextSafe(() => { const duration: number = 0.4; if (mainContainer.current && navContainer.current) { gsap.set( mainContainer.current, { overflow: "auto" } ); gsap.to( navContainer.current, { opacity: 0, ease: "power2.in", duration } ); gsap.set( navContainer.current, { clipPath: "inset(100% 0% 0% 0%)", delay: duration } ); gsap.set( navContainer.current, { display: "none", delay: duration } ); } }); return ( <div id="nav-container" ref={navContainer}> <button className="nav-btn" id="close-nav-btn" onClick={closeNav}>Close</button> <div className="nav-wrapper"> <nav> <ul className="nav-pages"> <li>HOME</li> <li>ABOUT</li> <li>CONTACT</li> <li>PROJECTS</li> </ul> <hr /> <ul className="nav-socials"> <li>Instagram</li> <li>Linkedin</li> <li>Github</li> </ul> </nav> <p>Mirko Bellopede <br /> Full stack web developer Portfolio 2024 ©</p> </div> </div> ); }); export default Navbar
内容的提问来源于stack exchange,提问作者Mirko Bellopede
相关产品推荐
相关产品推荐

