简体   繁体   English

如何将 removeEventListener 与组件 state 同步?

[英]How can I synchronise removeEventListener with component state?

sorry about the messy code.对混乱的代码感到抱歉。 Really getting myself in a tangle here.真的让自己在这里纠结。

I have a Nav component that I want to hide when the user scrolls.我有一个Nav组件,我想在用户滚动时隐藏它。 The scroll is detected using the event listener (which is now in useEffect , I don't really know why) which calls scrollDetect() .使用调用scrollDetect()的事件侦听器(现在在useEffect中,我真的不知道为什么)检测到滚动。

scrollDetect then sets a state variable, scrollState which is hooked up to the CSS via styled components.然后scrollDetect设置一个 state 变量scrollState ,它通过样式组件连接到 CSS 。

It all works very well, except that I want to stop the event listener when the nav "tray" is open.一切都很好,除了我想在导航“托盘”打开时停止事件侦听器。 The open state of the nav tray is stored in isOpen[1] , but it's just not being updated in the right order.导航托盘的打开 state 存储在isOpen[1]中,但只是没有按正确的顺序更新。 Whenever the nav tray is open, the buttons are still hiding on scroll.每当导航托盘打开时,按钮仍然隐藏在滚动条上。 To see the behavior I'm referring to, check out erasebegin.net.要查看我所指的行为,请查看 erasebegin.net。 Try clicking one of the menu buttons and then scrolling the window.尝试单击其中一个菜单按钮,然后滚动 window。

I have pored over all kinds of guides, posts and documentation, but am going in so many circles and going a little crazy over this, please help.我已经仔细研究了各种指南、帖子和文档,但是我在很多圈子里走来走去,对此有点疯狂,请帮忙。

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);
  };

You are not removing the event listener correctly.您没有正确删除事件侦听器。 Try the following:尝试以下操作:

 useEffect(() => { if (isOpen[1]) { document.addEventListener("scroll", scrollDetect); } else { document.removeEventListener("scroll", scrollDetect); } return () => document.removeEventListener("scroll", scrollDetect); }, [isOpen]);

You need two useEffect:你需要两个useEffect:

  1. This will create a listener one time:这将创建一个监听器一次:

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

  2. Then another one will remove it when the isOpen[1] will be falsy:然后当 isOpen[1] 为假时,另一个将删除它:

    useEffect(() => { if (.isOpen[1]) { document,removeEventListener("scroll"; scrollDetect), } }; [isOpen]); useEffect(() => { if (.isOpen[1]) { document,removeEventListener("scroll"; scrollDetect), } }; [isOpen]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM