Ada*_*mer 6 javascript reactjs react-hooks
状态确实在滚动上设置,但从事件侦听器记录,它似乎停留在初始值。
我想这与scrolling定义副作用时设置有关,但是我怎么能从滚动中触发状态更改呢?我假设的任何窗口事件也是如此。
这是一个代码和框示例:https ://codesandbox.io/s/react-test-zft3e
const [scrolling, setScrolling] = useState(false);
useEffect(() => {
window.addEventListener("scroll", () => {
console.log(scrolling);
if (scrolling === false) setScrolling(true);
});
}, []);
return (
<>
scrolling: {scrolling}
</>
);
Run Code Online (Sandbox Code Playgroud)
sky*_*yer 10
所以你的匿名函数被锁定在 的初始值上scrolling。这就是闭包在 JS 中的工作方式,你最好找一些关于它的漂亮文章,这可能会很棘手,而且钩子严重依赖闭包。
到目前为止,这里有 3 种不同的解决方案:
useEffect(() => {
const scrollHandler = () => {
if (scrolling === false) setScrolling(true);
};
window.addEventListener("scroll", scrollHandler);
return () => window.removeEventListener("scroll", scrollHandler);
}, [scrolling]);
Run Code Online (Sandbox Code Playgroud)
而这条路确保您在返回的清理从功能useEffect。这是很好的默认方法,但对于滚动它可能会影响性能,因为滚动事件触发太频繁。
const scrolling = useRef(false);
useEffect(() => {
const handler = () => {
if (scrolling.current === false) scrolling.current = true;
};
window.addEventListener("scroll", handler);
return () => window.removeEventListener("scroll", handler);
}, []);
return (
<>
scrolling: {scrolling}
</>
);
Run Code Online (Sandbox Code Playgroud)
缺点:更改 ref 不会触发重新渲染。所以你需要有一些其他变量来改变它触发重新渲染。
(我认为这是首选方式):
useEffect(() => {
const scrollHandler = () => {
setScrolling((currentScrolling) => {
if (!currentScrolling) return true;
return false;
});
};
window.addEventListener("scroll", scrollHandler);
return () => window.removeEventListener("scroll", scrollHandler);
}, []);
Run Code Online (Sandbox Code Playgroud)
注顺便说一句,即使一次性使用效果你更好的回报清理功能反正。
PS 现在您还没有设置scrolling为false,因此您可以摆脱 condition if(scrolling === false),但可以肯定的是,在现实世界中,您也可能会遇到类似的情况。
这意味着此时的变量也被“捕获”,因为在重新渲染时,您不会重新初始化事件侦听器。
这有点像安装时刻的快照。
如果将 console.log 移到外部,您会看到它随着重新渲染的发生而变化,并再次设置滚动值。
const [scrolling, setScrolling] = useState(false);
useEffect(() => {
window.addEventListener("scroll", () => {
if (scrolling === false) setScrolling(true);
});
}, []);
console.log(scrolling);
return (
<>
scrolling: {scrolling}
</>
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2072 次 |
| 最近记录: |