2 回答

TA貢獻1815條經(jīng)驗 獲得超6個贊
正如您在評論中提到的,window.addEventListener("scroll", runOnScroll)事件監(jiān)聽器位于返回函數(shù)之前,因此將配置多個監(jiān)聽器,因為 React 將在每次重新渲染時運行函數(shù)體。
您需要在掛鉤中添加事件偵聽器useEffect,并在組件卸載時刪除/清理偵聽器。
在給定的代碼中,事件偵聽器在每個渲染上執(zhí)行,因此將配置多個偵聽器。
解決方案:
您可以在鉤子中添加偵聽器useEffect并在回調(diào)中刪除偵聽器useEffect,并傳遞一個空數(shù)組作為依賴項(僅運行鉤子一次),使用這種方法將只有一個偵聽器。
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 (
<>
</>
)
}

TA貢獻1111條經(jīng)驗 獲得超0個贊
您當(dāng)前的問題是每次渲染組件時都添加一個新的滾動事件偵聽器。因此,在第一次渲染之后,您將獲得 1 個事件偵聽器,在第二次渲染之后,您將獲得 2 個事件偵聽器,在第三次渲染之后,您將獲得 3 個事件偵聽器,等等。這基本上是內(nèi)存泄漏,因為它們永遠(yuǎn)不會被刪除。
通過使用,useState
您可以控制添加事件處理程序的頻率,但更重要的是您可以從useEffect
.?
所有對回調(diào)本身中未定義的變量的引用都應(yīng)添加到依賴項列表中( 的第二個數(shù)組參數(shù)useState
)。除非保證這些變量的身份是穩(wěn)定的(對象/值保持不變)。
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
永遠(yuǎn)不會改變,因此可以將它們排除在依賴項列表之外。但是,由于您沒有提供任何有關(guān)style_project1
我添加的信息,只是為了確定一下。如果您知道這將始終保存相同的對象/值,您可以將依賴項列表更改為[]
.
如果您不指定依賴項列表,事情仍然有效,但回調(diào)將在每次渲染后執(zhí)行。這意味著每次渲染組件時,都會刪除先前的滾動事件并添加新的滾動事件。通過添加依賴項列表,只有當(dāng)列表中的值發(fā)生更改時,它才會重新運行(并預(yù)先清理)。這應(yīng)該更加罕見,從而獲得更好的性能。
添加回答
舉報