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

React TypeScript类组件如何正确保存元素ref供resize事件使用

问题核心原因

你遇到resize事件触发时ref值为null,是两处错误写法导致的:

  1. ref类型定义错误:React.LegacyRef<HTMLDivElement>是兼容旧版字符串ref、回调ref的联合类型,和React.createRef()返回的RefObject类型不匹配,导致DOM挂载阶段无法正确把元素实例赋值给ref的current属性。
  2. 事件绑定时机不合理:在constructor中绑定resize事件时,组件还未完成挂载,目标DOM节点还未渲染完成,不过这个问题会在组件挂载后自动消失,不是ref持续为null的核心原因。
正确实现代码
import React, { Component } from 'react';

// 按业务实际定义Props、State类型即可
interface CarouselProps {}
interface CarouselState {}

export default class Carousel extends Component<CarouselProps, CarouselState> {
  // 正确定义ref类型,直接初始化赋值
  private carouselRef = React.createRef<HTMLDivElement>();

  componentDidMount() {
    // DOM挂载完成后再绑定resize事件
    window.addEventListener('resize', this.resizeCarouselElements);
    // 初始化时主动触发一次,拿到元素初始状态
    this.resizeCarouselElements();
  }

  componentWillUnmount() {
    // 组件卸载时移除事件监听,避免内存泄漏
    window.removeEventListener('resize', this.resizeCarouselElements);
  }

  resizeCarouselElements = () => {
    // 增加非空判断,覆盖极端场景下ref未挂载的情况
    if (this.carouselRef.current) {
      const targetElement = this.carouselRef.current;
      // 此处可正常读取目标元素的尺寸、位置等状态,例:
      // const elementWidth = targetElement.offsetWidth;
      // const elementHeight = targetElement.offsetHeight;
    }
  };

  render() {
    return (
      <div className='name' ref={this.carouselRef}>
        {/* 轮播业务内容 */}
      </div>
    );
  }
}
Ref存储最佳实践
  • 禁止将ref存入组件state:ref的变动不会触发组件重渲染,存入state没有实际意义,反而会引发不必要的重渲染和类型异常。
  • 类组件中直接用类的私有实例属性存储ref即可:这是官方推荐的标准写法,ref对象和组件实例生命周期一致,访问方便,不会被意外篡改。
  • 不要在constructor、render执行阶段直接读取ref.current:这两个阶段DOM还未完成挂载/更新,读取到的要么是null要么是过期的DOM实例,读取操作要放在componentDidMount、componentDidUpdate生命周期,或者事件回调、用户交互触发的方法中。
  • 函数组件中使用useRef存储DOM引用或者其他不需要触发重渲染的可变值,逻辑和类组件实例属性存ref完全一致,ref对象在组件全生命周期保持引用稳定。
  • 除了DOM引用,定时器ID、上一轮props/state缓存值这类不需要触发重渲染的可变数据,都适合存在ref中,不要存入state。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 17:51:24