cbdeveloper
cbdeveloper

Reputation: 31335

How to set up an event listener and remove it after first fired event using react hooks?

I want' to set up an event listener to get only the first touchstart event on window. Once that happens, I want to remove that listener.

I'm using React Hooks.

QUESTION

I want to know if this is right, or if there's a better approach:

useEffect(() => {
    function onFirstTouch() {
      setWindowTouch(true);
      window.removeEventListener('touchstart', onFirstTouch, false);
    }
    window.addEventListener('touchstart', onFirstTouch);
  }, []);

It seems correct, but also feels that I'm going to set the listener again, when my component gets unmounted.


NOTE:

I know I could do something like this (use a "hasTouched" ref to check if the first event has already fired and ignore further events), but this is not exactly the same thing.

useEffect(() => {

    function handleTouch() {
      if (hasTouched.current === true) {
        return;
      }
      hasTouched.current = true;
      setWindowTouch(true);
    }

    window.addEventListener('touchstart', handleTouch);
    return () => window.removeEventListener('touchstart', handleTouch);
  }, []);

Upvotes: 1

Views: 813

Answers (1)

Ryan Cogswell
Ryan Cogswell

Reputation: 80976

The main issue I see is that you need to clean up the listener on unmount in case a touch never occurs, so that a touch after unmount doesn't try to act on your unmounted component.

So I would change it to the following:

useEffect(() => {
    function onFirstTouch() {
      // The order of these two lines shouldn't really matter, but I would
      // remove the listener before triggering a re-render via setWindowTouch
      window.removeEventListener('touchstart', onFirstTouch);
      setWindowTouch(true);
    }
    window.addEventListener('touchstart', onFirstTouch);
    return () => window.removeEventListener('touchstart', onFirstTouch);
  }, []);

Regarding:

feels that I'm going to set the listener again, when my component gets unmounted

The only thing that would be executed on unmount is the returned function (i.e. () => window.removeEventListener('touchstart', onFirstTouch)). It would only set the listener again if the component gets re-mounted.

Upvotes: 2

Related Questions