React中如何正确为ref绑定的自定义元素添加并清理事件监听?
问题原因
报错的核心是你在组件作用域声明的let eventRef是普通函数变量,每次组件重新渲染都会被重置,useEffect内部对它的赋值无法跨渲染周期保留,所以才会触发React的规则提示。
修复方案
你完全不需要额外声明eventRef变量,直接使用已有的textRef即可。另外要注意一个常见坑:原生addEventListener监听自定义事件不需要加on前缀,需要和自定义元素实际派发的事件名保持一致,你现在写的onCustomEvent大概率会监听不到事件。
修复后的完整代码如下:
export function App() { const textRef = useRef<DemoTextElement>(null); const logEvent = (e) => { console.log(e) } useEffect(() => { const element = textRef.current; if(!element) return; // 事件名要和自定义元素派发的名称一致,不要加on前缀 element.addEventListener('customEvent', logEvent); return () => { element.removeEventListener('customEvent', logEvent); } }, [logEvent]) // 将logEvent加入依赖数组避免闭包问题 return ( <div className={styles.app}> <demo-text ref={textRef}/> </div> ); }
可选优化点
- 如果
logEvent函数逻辑不会变化,可以用useCallback包裹,避免useEffect频繁重新执行:
const logEvent = useCallback((e) => { console.log(e) }, [])
- 如果你确实需要单独存储绑定事件的元素引用,就再声明一个useRef来存,不要用普通let变量:
const eventRef = useRef<DemoTextElement | null>(null); // 赋值时使用 eventRef.current = 目标元素
内容的提问来源于stack exchange,提问作者Crocsx
相关产品推荐
相关产品推荐

