亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

ReactJS setState 僅一次

ReactJS setState 僅一次

烙印99 2023-07-06 16:34:19
我正在嘗試根據網頁的 Y 滾動位置設置導航欄背景顏色。問題是,一旦我進入要設置導航欄背景狀態的 Y 坐標之間,它就不會停止設置,直到頁面凍結。這是我的代碼,以便更好地理解:獲取 Y 滾動位置,檢查其是否在 600 和 650 之間,如果為 true,則設置導航欄背景顏色:const [navbarBg, setNavbarBg] = useState(style_buttons)function runOnScroll() {  const scrolled = window.scrollY  if (scrolled > 600 && scrolled < 650) {    setNavbarBg(style_project1)  }}window.addEventListener("scroll", runOnScroll)即使我沒有滾動并且我不知道如何打破它,它也會不斷設置狀態。我嘗試使用 UseEffect 但我認為我不清楚如何使用它。有人可以幫忙嗎?
查看完整描述

2 回答

?
紅糖糍粑

TA貢獻1815條經驗 獲得超6個贊

正如您在評論中提到的,window.addEventListener("scroll", runOnScroll)事件監聽器位于返回函數之前,因此將配置多個監聽器,因為 React 將在每次重新渲染時運行函數體。


您需要在掛鉤中添加事件偵聽器useEffect,并在組件卸載時刪除/清理偵聽器。


在給定的代碼中,事件偵聽器在每個渲染上執行,因此將配置多個偵聽器。


解決方案:


您可以在鉤子中添加偵聽器useEffect并在回調中刪除偵聽器useEffect,并傳遞一個空數組作為依賴項(僅運行鉤子一次),使用這種方法將只有一個偵聽器。


const someComponent = function () {


    const [navbarBg, setNavbarBg] = useState(style_buttons)

    useEffect(() => {

        window.addEventListener("scroll", runOnScroll)

        return () => {

            window.removeEventListener("scroll", runOnScroll);

        }

    },[]);

    function runOnScroll() {

        const scrolled = window.scrollY

        if (scrolled > 600 && scrolled < 650) {

            setNavbarBg(style_project1)

        }

    }

    return (

        <>

        </>

    )

}


查看完整回答
反對 回復 2023-07-06
?
catspeake

TA貢獻1111條經驗 獲得超0個贊

您當前的問題是每次渲染組件時都添加一個新的滾動事件偵聽器。因此,在第一次渲染之后,您將獲得 1 個事件偵聽器,在第二次渲染之后,您將獲得 2 個事件偵聽器,在第三次渲染之后,您將獲得 3 個事件偵聽器,等等。這基本上是內存泄漏,因為它們永遠不會被刪除。

通過使用,useState您可以控制添加事件處理程序的頻率,但更重要的是您可以從useEffect.?

所有對回調本身中未定義的變量的引用都應添加到依賴項列表中( 的第二個數組參數useState)。除非保證這些變量的身份是穩定的(對象/值保持不變)。

const [navbarBg, setNavbarBg] = useState(style_buttons)


useState(() => {

? function runOnScroll() {

? ? const scrolled = window.scrollY;

? ? if (scrolled > 600 && scrolled < 650) {

? ? ? setNavbarBg(style_project1);

? ? }

? }

? window.addEventListener("scroll", runOnScroll);

? return () => window.removeEventListener("scroll", runOnScroll);

}, [style_project1]);

由于我們知道window并且setNavbarBg永遠不會改變,因此可以將它們排除在依賴項列表之外。但是,由于您沒有提供任何有關style_project1我添加的信息,只是為了確定一下。如果您知道這將始終保存相同的對象/值,您可以將依賴項列表更改為[].

如果您不指定依賴項列表,事情仍然有效,但回調將在每次渲染后執行。這意味著每次渲染組件時,都會刪除先前的滾動事件并添加新的滾動事件。通過添加依賴項列表,只有當列表中的值發生更改時,它才會重新運行(并預先清理)。這應該更加罕見,從而獲得更好的性能。


查看完整回答
反對 回復 2023-07-06
  • 2 回答
  • 0 關注
  • 176 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號