Skip to content
Advertisement

How to use useEffect Hook to execute the operation only once?

I wanted to make the modal popup if someone leaves the window.

I tried the following code:

React.useEffect(() => {
    const popupWhenLeave = (event) => {
      if (
        event.clientY <= 0 ||
        event.clientX <= 0 ||
        event.clientX >= window.innerWidth ||
        event.clientY >= window.innerHeight
      ) {
        handleClickOpen();
      }
    };
    document.addEventListener("mouseleave", popupWhenLeave);

    return () => {
      document.removeEventListener("mouseleave", popupWhenLeave);
    };
  }, []);

The above code helped me but became annoying as it pops up every interval. I tried adding a new state to run the code only once:

const [cursorOut, setCursorOut] = useState(false);

React.useEffect(() => {
    const popupWhenLeave = (event) => {
      if (
        event.clientY <= 0 ||
        event.clientX <= 0 ||
        event.clientX >= window.innerWidth ||
        event.clientY >= window.innerHeight
      ) {
        handleClickOpen();
      }
    };
    if(!cursorOut) {
       document.addEventListener("mouseleave", popupWhenLeave);
       setCursorOut(true);
    }

    return () => {
      document.removeEventListener("mouseleave", popupWhenLeave);
    };
  }, []);

The above code also ran the same as the previous one i.e. every time the modal would pop up.

I tried to add the dependency to useEffect [cursorOut] but now it won’t pop the modal.

I need to pop up the modal only once on the page when the cursor is out and then stop.

P.S. I also tried without useEffect and it doesn’t work.

Advertisement

Answer

Your useEffect function is only called once, when the dependency array is empty. However, your useEffect function adds an event listener to the page, which fill be called every time the event occurs.

If you want to only listen to the event once, you should remove the event listener in the popupWhenLeave function and not only in the useEffect clean up function you return at the end.

  React.useEffect(() => {
    const popupWhenLeave = (event) => {
      if (
        event.clientY <= 0 ||
        event.clientX <= 0 ||
        event.clientX >= window.innerWidth ||
        event.clientY >= window.innerHeight
      ) {
        handleClickOpen();
        document.removeEventListener("mouseleave", popupWhenLeave);
      }
    };
    document.addEventListener("mouseleave", popupWhenLeave);

    return () => {
      document.removeEventListener("mouseleave", popupWhenLeave);
    };
  }, []);

Sidenote: If your component is recreated because e.g. a parent component changed, the useEffect function will be called again regardless of the contents of the dependency array.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement