React useEffect中清理querySelectorAll绑定的事件监听时出现TypeError报错的问题求助
React useEffect中清理querySelectorAll绑定的事件监听时出现TypeError报错的问题求助
兄弟,我一眼就瞅到你代码里的两个核心问题,这就是报错的根源:
首先,你用document.querySelectorAll("li")拿到的child是个NodeList集合,不是单个DOM元素!集合本身压根没有removeEventListener这个方法,只有单个DOM元素才有,所以直接调用child.removeEventListener肯定会抛出TypeError。
其次,你的清理函数里的回调完全不对啊!绑定事件时用的是匿名箭头函数,但清理时传的是console.log("parent clicked")——这根本不是同一个函数引用,就算是单个元素,也没法正确移除监听,等于白写了清理逻辑。
给你改好的完整代码,直接就能用:
export default function EventList() { // 把事件回调抽成独立函数,保证绑定和清理用同一个引用 const handleParentClick = () => { console.log("parent clicked"); }; const handleChildClick = (event) => { event.stopPropagation(); console.log("child clicked"); }; useEffect(() => { const parent = document.querySelector("ul"); const child = document.querySelectorAll("li"); if (parent) { parent.addEventListener("click", handleParentClick, true); } if (child) { child.forEach((list) => { list.addEventListener("click", handleChildClick); }); } return () => { // 清理父元素监听,先判断元素是否存在 if (parent) { parent.removeEventListener("click", handleParentClick, true); } // 清理子元素监听:遍历NodeList,给每个元素单独移除 if (child) { child.forEach((list) => { list.removeEventListener("click", handleChildClick); }); } }; }, []); // 空依赖数组,只在组件挂载和卸载时执行 return ( <> <ul> <li>name</li> <li>age</li> <li>address</li> </ul> </> ); }
再给你划几个以后要注意的点:
- 只要是
querySelectorAll返回的集合,不管是绑定还是移除事件,都得用forEach遍历每个元素操作,不能直接对集合调用单个元素的方法。 - 事件监听的回调一定要用具名函数,别用匿名函数!匿名函数每次渲染都是新的引用,清理的时候根本找不到要移除的那个监听,等于造成了内存泄漏。
- 不管是绑定还是清理,都要加个空值判断,比如
if (parent),防止组件卸载时DOM已经被销毁,导致空值报错。
内容来源于stack exchange
相关产品推荐
相关产品推荐

