簡體   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