useEffect+addEventListener 的坑

Posted by CodingWithAlice on July 26, 2025

useEffect+addEventListener 的坑

总结:

  • 即使 React 组件重新渲染,事件监听绑定的依旧是 当时的函数引用,捕获的是当时的作用域 和变量
背景问题

​ addEventListener 事件监听器绑定的回调函数,一直是旧的

原因

​ addEventListener 事件监听器 绑定时 捕获的是 当时的 props 和 state(当时的作用域和变量,旧的) -> 后续不会自动变化

  • 知识点1:addEventListener 绑定的是 当时的函数引用,后续 props 变化不会自动影响已经绑定的事件处理函数
  • 知识点2:React 的函数组件每次渲染都会生成新的函数,但 事件监听不会自动更新为新函数,除非手动解绑再绑定
方案

​ 必须在 useEffect 依赖里面,解绑 旧的,绑定 新的 -> 这样事件处理函数才会用到最新的 props

useEffect(() => {
    window.addEventListener('scroll', handleScroll);
    return () => {
      window.removeEventListener('scroll', handleScroll); // 清理旧监听
    };
  }, [handleScroll]); // 依赖 handleScroll(其变化时会重新绑定)