如何将ref传递给被高阶组件包裹的子组件——TypeScript报错解决方案咨询
解决TypeScript下HOC包裹组件时的ref传递问题
嘿,我刚好碰到过类似的问题,你的问题核心在于高阶组件(SectionWrapper)没有处理ref的透传——ref并不是普通的props,默认情况下HOC不会自动把它传递给内部的组件,所以TypeScript才会报错说ref不存在于组件的属性中。
下面是一步步的解决方案:
1. 修改高阶组件,支持ref透传
原来的HOC只是简单地传递了props,但忽略了ref。我们需要把HOC改成使用forwardRef,这样就能把外部传入的ref传递给被包裹的组件:
import Container from "react-bootstrap/Container"; import React, { forwardRef, ForwardRefRenderFunction } from "react"; // 泛型P表示组件的props类型,默认是空对象 export default function SectionWrapper<P = {}>( Component: ForwardRefRenderFunction<HTMLElement, P> ) { // 使用forwardRef接收外部传入的ref,并传递给内部Component return forwardRef<HTMLElement, P>((props, ref) => { return ( <section> <Container> <Component {...props} ref={ref} /> </Container> </section> ); }); }
2. 优化子组件的类型定义
尽量避免使用any,给About组件明确的类型,让TypeScript能更好地检查类型:
import SectionWrapper from "../../wrappers/section/SectionWrapper"; import React, { forwardRef } from "react"; // 定义组件的props类型(这里没有额外props,所以是空对象) type AboutProps = {}; // 使用forwardRef明确指定ref的类型是HTMLElement,props类型是AboutProps const About = forwardRef<HTMLElement, AboutProps>((props, ref) => { return ( <div ref={ref} className="s__about" style={{ minHeight: "100vh" }}> <div></div> </div> ); }); export default SectionWrapper(About);
3. 完善父组件的ref类型
给aboutRef指定明确的类型,同时可以用可选链替代强制非空断言,让代码更安全:
const App = () => { const aboutRef = useRef<HTMLElement>(null); // 明确ref指向HTMLElement function handleNavClick() { // 可选链操作符更安全,避免强制非空断言 aboutRef.current?.scrollIntoView({ behavior: "smooth" }); // 或者保留你原来的写法: // window.scrollTo(0, aboutRef.current!.offsetTop); } return ( <div> <Header onNavClick={handleNavClick} /> <Main> <Home /> <About ref={aboutRef} /> {/* 现在ref能正常传递了 */} <Contact /> </Main> <Footer /> </div> ); }; export default App;
为什么原来的代码会报错?
原来的HOC返回的是React.FC,而React.FC的props类型里并不包含ref——ref是React的特殊属性,只有使用forwardRef的组件才能接收它。当你给被HOC包裹的<About>组件传ref时,TypeScript会检测到这个属性不在组件的允许props列表里,所以抛出了TS2322错误。
通过上面的修改,我们让HOC也支持forwardRef,把外部的ref透传给内部的About组件,同时给所有部分加上了正确的TypeScript类型,这样就能解决问题啦。
内容的提问来源于stack exchange,提问作者TJDev
相关产品推荐
相关产品推荐

