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

React中useEffect内removeEventListener失效问题咨询

问题原因及解决方案
  • 核心原因:每次isIntersecting状态变化时,useEffect都会重新执行,内部定义的handleParallax是全新的函数实例。当你调用removeEventListener时,传入的是当前这次渲染生成的新函数,而之前绑定到scroll事件上的是上一次渲染的旧函数——两个函数的引用完全不同,所以移除操作找不到对应的监听,旧的handleParallax自然还会在滚动时触发执行。

  • 解决方案:用useCallback缓存handleParallax函数,确保每次渲染时函数引用保持一致,同时在useEffect的清理函数中补充移除操作,避免组件卸载后残留监听:

// ...observer code here
const handleParallax = useCallback(() => {
    let items = document.querySelectorAll('.item')
    items.forEach(item => {
        let distance = (window.scrollY || window.pageYOffset),
            distanceFinal = item.parentNode.offsetTop - distance,
            multi = 45;
        console.log((distanceFinal * multi)/500);
        let calc = `translate3d(0, calc(370px + ${((distanceFinal * multi)/500)}px), 0)`;
        item.setAttribute('style',
            `transform: ${calc};
            -ms-transform: ${calc};
            -webkit-transform: ${calc};`
        );
    });
}, []); // 若函数内用到其他状态/变量,需添加到依赖数组中

useEffect(() => {
    if (isIntersecting) {
        console.log('enter')
        window.addEventListener('scroll', handleParallax, true)
    } else {
        console.log('exit')
        window.removeEventListener('scroll', handleParallax, true);
    }

    // 组件卸载时强制移除监听,防止内存泄漏
    return () => {
        window.removeEventListener('scroll', handleParallax, true);
    }
}, [isIntersecting, handleParallax]); // 将缓存后的handleParallax加入依赖

内容的提问来源于stack exchange,提问作者Nathan Bernard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 02:04:55