繁体   English   中英

为什么 useEffect() 中的 addEventListener 和 removeEventListener 需要箭头 function?

[英]Why does addEventListener and removeEventListener inside useEffect() require an arrow function?

如果用户滚动到顶部,我正在尝试将 onTop state 设置为 true ,否则设置为 false 。 我尝试了以下。

function Test()
{
    const [ onTop, setOnTop ] = useState( true )

    const watchScroll = () =>
    {
        if ( window.scrollY < 100 ) setOnTop( true )
        else setOnTop( false )
    }

    useEffect(() => {
        window.addEventListener(`scroll`, watchScroll )
        return  window.removeEventListener(`scroll`, watchScroll )
    }, [ watchScroll ])

    return (

        <div>{ onTop ? `On Top` : `Not On top` }</div>

    )
}

上面的示例不起作用,但也不会引发错误。

function Test()
{
    const [ onTop, setOnTop ] = useState( true )

    const watchScroll = () =>
    {
        if ( window.scrollY < 100 ) setOnTop( true )
        else setOnTop( false )
    }

    useEffect(() => {
        window.addEventListener(`scroll`, () => watchScroll() )
        return  window.removeEventListener(`scroll`, () => watchScroll() )
    }, [ watchScroll ])

    return (

        <div>{ onTop ? `On Top` : `Not On top` }</div>

    )
}

请注意,我在第二个参数 function 中添加了箭头和大括号。 上面的示例按预期工作。 谁能解释为什么? 非常感谢!

如果你想清理你的效果,你需要返回一个 function。

useEffect(() => {
        window.addEventListener(`scroll`, watchScroll )
        return  () => window.removeEventListener(`scroll`, watchScroll )
}, [ watchScroll ])

您最初的 function 无法正常工作的原因是,在每次重新渲染时,都会创建一个 function 的新实例,并且由于您将 ZC1C425268E67385D1AB5074F14C 的依赖项传递给使用,因此删除了前一个实例。 此外,由于您没有在清理 function 中执行window.removeEventListener ,因此它会立即运行,从而导致侦听器立即被删除。

您可以通过以下方式解决它

function Test()
{
    const [ onTop, setOnTop ] = useState( true )

    const watchScroll = useCallback(() =>
    {
        if ( window.scrollY < 100 ) setOnTop( true )
        else setOnTop( false )
    }, []);

    useEffect(() => {
        window.addEventListener(`scroll`, watchScroll )
        return () => window.removeEventListener(`scroll`, watchScroll )
    }, [ watchScroll ])

    return (

        <div>{ onTop ? `On Top` : `Not On top` }</div>

    )
}

或者

function Test()
{
    const [ onTop, setOnTop ] = useState( true )

   
    useEffect(() => {
        const watchScroll = () => {
           if ( window.scrollY < 100 ) setOnTop( true )
           else setOnTop( false )
       }

        window.addEventListener(`scroll`, watchScroll )
        return ()=> window.removeEventListener(`scroll`, watchScroll )
    }, [ ])

    return (

        <div>{ onTop ? `On Top` : `Not On top` }</div>

    )
}

另请注意,使用箭头函数,您的解决方案有效,因为要删除EventListener,您需要传递相同的removeEventListener参考才能使其正常工作,如果您使用箭头 function,则侦听器不会清理,因此您的实现工作

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM