Reputation: 31335
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
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