如何将removeEventListener与组件状态同步?

问题描述

很抱歉,代码混乱。真的让我感到纠结。

我有一个Nav组件,我想在用户滚动时隐藏它。使用事件监听器(现在位于useEffect中,但我不知道为什么)检测到滚动,该事件监听器调用scrollDetect()

scrollDetect然后设置状态变量scrollState,该状态变量通过样式化组件连接到CSS。

这一切都很好,除了在导航“托盘”打开时我想停止事件监听器。导航托盘的打开状态存储在isOpen[1]中,但只是没有以正确的顺序进行更新。每当导航托盘打开时,按钮仍在滚动状态下隐藏。要查看我所指的行为,请查看deletebegin.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(() => {
    if (isOpen[1]) {
       document.addEventListener("scroll",scrollDetect);
    } else {
      document.removeEventListener("scroll",scrollDetect);
    }

    return () => document.removeEventListener("scroll",scrollDetect);
  },[isOpen]);

,

您需要两个useEffect:

  1. 这将一次创建一个侦听器:

    useEffect(()=> { document.addEventListener(“ scroll”,scrollDetect); },[]);

  2. 然后,当isOpen [1]虚假时,另一个将其删除:

    useEffect(()=> { 如果(!isOpen [1]){ document.removeEventListener(“ scroll”,scrollDetect); } },[isOpen]);

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...