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
相关产品推荐
相关产品推荐

