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

React添加resize事件监听出现TS2769错误的原因解析

React事件监听器报错原因解析

核心问题:事件回调的类型与执行时机错误

原代码里的setWidth(ref.current.offsetWidth)存在两个致命问题:

  • 类型不匹配:addEventListener要求第二个参数是函数类型的回调,但你这里直接调用了setWidth,它的返回值是void(无返回值),完全不符合事件监听器对回调函数的类型要求,所以TypeScript抛出TS2769类型错误。
  • 执行时机错误:这样写会在useLayoutEffect执行的瞬间就立刻调用setWidth,而不是等到resize事件触发时才执行,完全违背了事件监听的初衷。

为什么修改后能正常运行?

改成handleResize的写法解决了所有问题:

  1. 符合类型要求:handleResize是一个标准函数,完全匹配事件监听器对回调的类型要求(事件回调默认接收事件对象,这里不需要可以省略)。
  2. 正确的执行时机:只有当resize事件触发时,才会调用handleResize,进而执行setWidth更新状态。
  3. 可正确移除监听:addEventListener和removeEventListener使用了同一个handleResize函数引用,组件卸载时能正常移除事件监听器,避免内存泄漏。

额外修正点

你修改后的代码里有个小错误:offsetWidth是DOM元素的属性不是方法,不需要加括号,正确写法如下:

const handleResize = () => {
    if(ref.current) { // 增加空值判断,避免null报错
        setWidth(ref.current.offsetWidth)
    }
}

完整修正后的代码示例

import React, { useState, useRef, useLayoutEffect } from 'react';

const DemoComponent = () => {
    const [width, setWidth] = useState<number>(0);
    const ref = useRef<HTMLHeadingElement>(null);

    const handleResize = () => {
        if (ref.current) {
            setWidth(ref.current.offsetWidth);
        }
    };

    useLayoutEffect(() => {
        const element = ref.current;
        if (element) {
            element.addEventListener('resize', handleResize);
        }

        return () => {
            if (element) {
                element.removeEventListener('resize', handleResize);
            }
        };
    }, []);

    return <h1 ref={ref}>当前宽度:{width}px</h1>;
};

export default DemoComponent;

内容的提问来源于stack exchange,提问作者four-eyes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 22:09:24