React添加resize事件监听出现TS2769错误的原因解析
React事件监听器报错原因解析
核心问题:事件回调的类型与执行时机错误
原代码里的setWidth(ref.current.offsetWidth)存在两个致命问题:
- 类型不匹配:
addEventListener要求第二个参数是函数类型的回调,但你这里直接调用了setWidth,它的返回值是void(无返回值),完全不符合事件监听器对回调函数的类型要求,所以TypeScript抛出TS2769类型错误。 - 执行时机错误:这样写会在
useLayoutEffect执行的瞬间就立刻调用setWidth,而不是等到resize事件触发时才执行,完全违背了事件监听的初衷。
为什么修改后能正常运行?
改成handleResize的写法解决了所有问题:
- 符合类型要求:
handleResize是一个标准函数,完全匹配事件监听器对回调的类型要求(事件回调默认接收事件对象,这里不需要可以省略)。 - 正确的执行时机:只有当
resize事件触发时,才会调用handleResize,进而执行setWidth更新状态。 - 可正确移除监听:
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
相关产品推荐
相关产品推荐

