javascript - 如何将 removeEventListener 与组件状态同步?
问题描述
对混乱的代码感到抱歉。真的让自己在这里纠结。
我有一个Nav
组件要在用户滚动时隐藏。使用useEffect
调用scrollDetect()
.
scrollDetect
然后设置一个状态变量,scrollState
该变量通过样式组件连接到 CSS。
一切都很好,除了我想在导航“托盘”打开时停止事件侦听器。导航托盘的打开状态存储在 中isOpen[1]
,但只是没有按正确的顺序更新。每当导航托盘打开时,按钮仍然隐藏在滚动条上。要查看我所指的行为,请查看 erasebegin.net。尝试单击其中一个菜单按钮,然后滚动窗口。
我已经仔细研究了各种指南、帖子和文档,但是我在很多圈子里走来走去,对此有点疯狂,请帮忙。
export default function Nav() {
const [isOpen, setIsOpen] = useState(["", false]);
const [envOpen, setEnvOpen] = useState(false);
const [scrollState, setScrollState] = useState("show");
// HIDE NAVBUTTONS ON DOWN SCROLL, REVEAL ON UP SCROLL
var lastScrollTop = window.pageYOffset || window.scrollTop;
const scrollDetect = () => {
if (isOpen[1] === false) {
var st = window.pageYOffset || document.documentElement.scrollTop;
if (st < lastScrollTop) {
setScrollState("show");
} else if (st > lastScrollTop) {
setScrollState("hide");
}
lastScrollTop = st <= 0 ? 0 : st;
}
};
useEffect(() => {
console.log(isOpen[1]);
const listener = document.addEventListener("scroll", scrollDetect);
const cleanup = () => {
document.removeEventListener("scroll", listener);
return cleanup;
};
}, [isOpen[1]]);
const setOpen = ([title, state]) => {
let newState = !state;
setIsOpen([title, newState]);
};
const envelopeOpen = () => {
setEnvOpen(true);
};
const envelopeClose = () => {
setEnvOpen(false);
};
解决方案
你需要两个useEffect:
这将创建一个监听器一次:
useEffect(() => { document.addEventListener("scroll", scrollDetect); }, []);
然后当 isOpen[1] 为假时,另一个将删除它:
useEffect(() => { if (!isOpen[1]) { document.removeEventListener("scroll", scrollDetect); } }, [isOpen]);
推荐阅读
- python - 如何将python代码输出存储到csv文件
- php - 将网页的一部分保存为 html
- javascript - jquery - 单页应用程序
- java - bean 遇到非应用程序异常;嵌套异常是:org.hibernate.exception.JDBCConnectionException:无法执行查询
- .net-core - EnvironmentTagHelper 在网页上呈现自己,包括所有内容
- c++ - 构建时发生 LNK2001 错误,但不是通过调试
- angular - 角度鼠标单击并水平拖动滚动
- python - 如何解决虚拟键代码的问题?
- python - 如何在python中对odient给出任意初始条件
- c# - 有没有更好的方法(最快)来获得最长的公共文件夹路径?