0

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. The scroll is detected using the event listener (which is now in useEffect, I don't really know why) which calls scrollDetect().

scrollDetect then sets a state variable, scrollState which is hooked up to the CSS via styled components.

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. 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. Try clicking one of the menu buttons and then scrolling the 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);
  };
Chris Haupt
  • 142
  • 1
  • 11
  • Could somebody please help. This seems impossible. `removeEventListener` is definitely being triggered, but _nothing_ is happening T_T the event listener remains firmly in place – Chris Haupt Aug 12 '20 at 19:04

2 Answers2

2

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]);
jank
  • 840
  • 4
  • 7
  • Thank you for your response :) Unfortunately this does not work. When I log the state of `isOpen[1]` in `useEffect` it is showing the correct state, but the event listener seems to still be active even when `isOpen[1]` is `true`... ``` useEffect(() => { console.log(isOpen[1]) if (isOpen[1]===false) { document.addEventListener("scroll", scrollDetect); } else { document.removeEventListener("scroll", scrollDetect); } }, [isOpen[1]]); ``` – Chris Haupt Aug 11 '20 at 20:01
  • Well, this is expected from the code above, isn't it? It's just an example how to correctly add and remove listeners :) – jank Aug 11 '20 at 20:24
  • It's not what I am expecting. What I am expecting is for the event listener to be removed when isOpen[1] is true, and for it to resume when isOpen[1] is false. It seems like such a simple thing to do, but nothing I have tried has worked! – Chris Haupt Aug 12 '20 at 09:47
1

You need two useEffect:

  1. This will create a listener one time:

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

  2. Then another one will remove it when the isOpen[1] will be falsy:

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

Abdul
  • 149
  • 4
  • Thank you Abdul, but again, this did not work. When I log `isOpen[1]` in the second useEffect, it is receiving the correct signal at the correct time, but the event listener remains active! – Chris Haupt Aug 12 '20 at 09:46
  • Can you share the latest code after making the changes that I proposed? – Abdul Aug 13 '20 at 09:07