React用useEffect绑定事件报addEventListener相关null类型错误如何解决
报错原因
- 核心触发原因是你执行
addEventListener的目标DOM不存在:useEffect回调执行时,id为rewards_modal的模态框节点还未渲染挂载到页面上,document.querySelector('#rewards_modal')返回null,对null访问方法就会抛出该类型错误。 - 现有代码还存在额外问题:当前useEffect没有传入第二个依赖数组参数,组件每次渲染都会重复执行事件绑定逻辑,且没有配置事件解绑的清理逻辑,会导致内存泄漏、重复触发事件回调的问题。
修复方案
方案1:优先使用React Ref获取DOM(推荐)
首先给你的模态框JSX元素绑定ref:
// 你的模态框元素处添加ref <div id="rewards_modal" className="modal" ref={modalRef}> {/* 模态框内容 */} <div className="modal-body"></div> </div>
然后修改useEffect逻辑,增加非空判断、依赖数组、事件清理逻辑:
import { useEffect, useRef } from 'react'; // 组件内定义ref const modalRef = useRef(null); useEffect(() => { const modalNode = modalRef.current; // 先判断节点存在再绑定事件 if (!modalNode) return; const handleModalShow = (e) => { const modalBody = modalNode.querySelector('.modal-body'); if (!modalBody) return; const handleScroll = () => { console.log('scroll y'); }; modalBody.addEventListener('scroll', handleScroll); // 返回scroll事件的清理函数,在模态框隐藏时或者组件卸载时解绑 return () => modalBody.removeEventListener('scroll', handleScroll); }; modalNode.addEventListener('shown.bs.modal', handleModalShow); // 组件卸载或者依赖变化时,解绑模态框的显示事件 return () => { modalNode.removeEventListener('shown.bs.modal', handleModalShow); }; // 如果模态框是条件渲染,把控制模态框显隐的状态变量加入依赖数组,比如[showModal] }, []);
方案2:保留querySelector写法,增加非空判断
如果不想修改原有DOM选择逻辑,只需要在调用方法前增加非空校验即可,同时补充清理逻辑:
useEffect(() => { const modalNode = document.querySelector('#rewards_modal'); if (!modalNode) return; const handleModalShow = (e) => { const modalBody = document.querySelector('.modal-body'); if (!modalBody) return; const handleScroll = () => console.log('scroll y'); modalBody.addEventListener('scroll', handleScroll); return () => modalBody.removeEventListener('scroll', handleScroll); }; modalNode.addEventListener('shown.bs.modal', handleModalShow); return () => modalNode.removeEventListener('shown.bs.modal', handleModalShow); // 同样按需补充依赖 }, []);
内容的提问来源于stack exchange,提问作者Zeeshan Khalid
相关产品推荐
相关产品推荐

