首先,使用类组件,可以很好地工作并且不会引起任何问题。
但是,在带有钩子(Hook)的功能组件中,即使我尝试使用滚动事件侦听器的函数handleScroll
设置状态,我的状态也无法更新,或者即使我使用了反跳功能,应用程序的性能也受到严重影响。
import React, { useState, useEffect } from "react";
import debounce from "debounce";
let prevScrollY = 0;
const App = () => {
const [goingUp, setGoingUp] = useState(false);
const handleScroll = () => {
const currentScrollY = window.scrollY;
if (prevScrollY < currentScrollY && goingUp) {
debounce(() => {
setGoingUp(false);
}, 1000);
}
if (prevScrollY > currentScrollY && !goingUp) {
debounce(() => {
setGoingUp(true);
}, 1000);
}
prevScrollY = currentScrollY;
console.log(goingUp, currentScrollY);
};
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
return (
<div>
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
</div>
);
};
export default App;
尝试在
useCallback
函数中使用handleScroll
钩子(Hook),但并没有太大帮助。我究竟做错了什么?如何在不影响性能的情况下从
handleScroll
设置状态?我已经为此问题创建了一个沙箱。
最佳答案
在您的代码中,我看到了几个问题:
1)useEffect中的[]
表示它将看不到任何状态变化,例如goingUp
的变化。它将始终看到goingUp
的初始值
2)debounce
不起作用。它返回一个新的去抖动功能。
3)通常,全局变量是一种反模式,认为它仅在您情况下有效。
4)您的滚动监听器不是被动的,如@skyboyer所述。
import React, { useState, useEffect, useRef } from "react";
const App = () => {
const prevScrollY = useRef(0);
const [goingUp, setGoingUp] = useState(false);
useEffect(() => {
const handleScroll = () => {
const currentScrollY = window.scrollY;
if (prevScrollY.current < currentScrollY && goingUp) {
setGoingUp(false);
}
if (prevScrollY.current > currentScrollY && !goingUp) {
setGoingUp(true);
}
prevScrollY.current = currentScrollY;
console.log(goingUp, currentScrollY);
};
window.addEventListener("scroll", handleScroll, { passive: true });
return () => window.removeEventListener("scroll", handleScroll);
}, [goingUp]);
return (
<div>
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
<div style={{ background: "orange", height: 100, margin: 10 }} />
</div>
);
};
export default App;
https://codesandbox.io/s/react-setstate-from-event-listener-q7to8
关于javascript - 从滚动事件监听器 react setState Hook ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57088861/