removeEventListener 在 UseEffect 中不起作用。

huangapple go评论66阅读模式
英文:

removeEventListener not working in UseEffect

问题

我的问题可能看起来很愚蠢,但我已经搜索了解决方案好几天,尝试了多次更改,但都没有成功。问题如下:

我有一个使用脚本执行视差效果的React组件。我使用一个事件监听器,所以当我在组件上滚动时,它会触发脚本。然而,我希望在继续滚动时删除这个事件监听器。removeEventListener 不起作用,所以当我切换页面时出现错误(因为脚本找不到 Div)。

这是我的组件(我删除了前端代码,只保留了逻辑部分):

const GridTextParallax = () => {

    // 当组件出现在页面上时触发脚本
    const { trigger, inView } = useInView({
        threshold: [0, 0.8],
    });
    
    
    const parallax = (scrolling) => {       
        if (scrolling > 0) {
            // 所有完美运行的视差逻辑
        }
    }

    useEffect(() => {
        if (inView) {
            document.addEventListener('scroll', () => {
                var scrolling = // 执行计算组件内滚动速率的逻辑;
                parallax(scrolling)
            });
            return () => { window.removeEventListener('scroll', parallax); };
        } else {
            console.log("在视口外")
            window.removeEventListener('scroll', parallax);
        }
    }, [inView]);


    return (
        <section id="layer" ref={trigger} >
            所有前端代码...
        </section>
    )
}

export default GridTextParallax 

我错过了什么?

非常感谢

英文:

My question may seems stupid but I searched the solution for days, tried multiple changes nothing works. Here it is:

I have a React component that uses a script to perform a parallax effect. I use an eventlistener so when I scroll on the component it fires the script. However, I would like to remove this eventlistener when I continue the scroll. The removeEventListener doesn't work so when I change page I got an error (because the script doesn't find the Div).

Here is my component (I removed the front code which works fine to just keep the logic):

const GridTextParallax = () =&gt; {

    //trigger the script when component appear on the page  
    const { trigger, inView } = useInView({
        threshold: [0, 0.8],
    });
    
    
    const parallax = (scrolling) =&gt; {       
        if (scrolling &gt; 0) {
            //All the parallax logic that works perfect
        }
    }

    useEffect(() =&gt; {
        if (inView) {
            document.addEventListener(&#39;scroll&#39;, () =&gt; {
                var scrolling = // perform the logic to calculate the scrolling rate within the component;
                    parallax(scrolling)
            });
            return () =&gt; { window.removeEventListener(&#39;scroll&#39;, parallax); };
        } else {
            console.log(&quot;outside viewport&quot;)
            window.removeEventListener(&#39;scroll&#39;, parallax);
        }
    }, [inView]);


    return (
        &lt;section id=&quot;layer&quot; ref={trigger} &gt;
            All the front end...
        &lt;/section&gt;
    )
}

export default GridTextParallax 

What did I miss?

Thanks a lot

答案1

得分: 1

你需要将相同的回调实例同时传递给addEventListenerremoveEventListener,以便移除监听器。在你的情况下,你将一个匿名箭头函数传递给addEventListener,而将paralax函数传递给removeEventListener

解决方法是将回调写入变量中,并在addEventListenerremoveEventListener中都使用它:

const cb = () => {
  var scrolling = // 在组件内部执行计算滚动速率的逻辑;
  parallax(scrolling)
}

addEventListener("scroll", cb)

return () => {
  removeEventListener("scroll", cb)
}
英文:

You need to pass the same instance of callback to both addEventListener and removeEventListener for the listener to be removed. In your case you're passing an anonymous arrow function to addEventListener and paralax function to removeEventListener.

The solution is to write the callback into a variable and use it in both addEventListener and removeEventListener:

const cb = () =&gt; {
  var scrolling = // perform the logic to calculate the scrolling rate within the component;
  parallax(scrolling)
}

addEventListener(&quot;scroll&quot;, cb)

return () =&gt; {
  removeEventListener(&quot;scroll&quot;, cb)
}

huangapple
  • 本文由 发表于 2023年6月29日 00:30:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76575101.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定