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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 08:43:02