You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React TypeScript中如何将useRef创建的Ref传递给子组件?

问题分析与解决方案

你的核心问题是forwardRef的泛型参数和回调函数参数使用错误,导致TypeScript类型不匹配。下面一步步拆解错误原因并给出正确实现:

错误根源

  1. 第一次定义组件时,forwardRef<HTMLElement, React.HTMLProps<HTMLElement>>((ref) => { ... })的回调函数只写了ref参数,但forwardRef的回调函数实际接收两个参数:第一个是组件props,第二个是ref。TS把你写的ref参数识别成了props(类型是React.HTMLProps<HTMLElement>),再把这个props传给section的ref属性,自然会出现类型不兼容的错误。
  2. 后续修改时,你没有正确声明forwardRef的泛型,而是直接给ref参数硬套类型,导致父组件传递ref时类型冲突。

正确实现步骤

1. 子组件(Introduction)的正确写法

使用forwardRef时,严格遵循泛型参数顺序:

  • 第一个泛型参数:ref要指向的DOM元素类型(这里是HTMLElement,对应section标签)
  • 第二个泛型参数:组件的props类型(如果你的组件不需要自定义props,用{}即可;如果需要透传section的原生属性,用React.HTMLAttributes<HTMLElement>)

代码示例:

import React, { forwardRef } from "react";
import myInfo from "../myInfo.json";

// 泛型第一个是ref类型,第二个是props类型
const Introduction = forwardRef<HTMLElement, React.HTMLAttributes<HTMLElement>>(
  (props, ref) => {
    // 把ref绑定到section,同时透传props(比如className、style等)
    return (
      <section ref={ref} className="Introduction" {...props}>  
          <p className="greeting">Welcome</p>
          <p className="intro">{myInfo.introduction}</p>
          <div className="picture">
            {/* <PixelateToUnpixelate src={myInfo.myPicture} /> */}
          </div>
      </section>
    );
  }
);

export default Introduction;

2. 父组件中正确使用ref

父组件创建ref时,明确指定ref的类型为HTMLElement(和子组件的泛型对应),避免TS推断为null类型导致的冲突:

import { useRef, useEffect } from "react";
import Introduction from "./Introduction";

const ParentComponent = () => {
  // 明确ref的类型为HTMLElement | null
  const introRef = useRef<HTMLElement>(null);

  useEffect(() => {
    if (!introRef.current) return;

    // 初始化IntersectionObserver监听可见性
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            console.log("Introduction组件进入视口");
            // 这里写你的逻辑,比如触发动画、统计曝光等
          } else {
            console.log("Introduction组件离开视口");
          }
        });
      },
      { threshold: 0.5 } // 自定义监听阈值
    );

    observer.observe(introRef.current);

    // 组件卸载时清理监听
    return () => observer.disconnect();
  }, []);

  return (
    <div>
      <Introduction ref={introRef} />
    </div>
  );
};

export default ParentComponent;

关键类型说明

  • forwardRef<T, P>:T是ref指向的DOM元素类型,P是组件的props类型。回调函数必须接收(props: P, ref: React.Ref<T>)两个参数。
  • useRef<T>(initialValue):T是ref.current的类型,这里我们初始值是null,所以TS会自动推断current的类型为T | null,刚好和IntersectionObserver的要求匹配。
  • 避免使用LegacyRef:这个类型是为了兼容React旧版的字符串ref,现代React推荐使用函数ref或ref对象,所以不需要手动指定LegacyRef。

内容的提问来源于stack exchange,提问作者CKang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 04:57:11