From fb5472bbbebc2b4f9615d7d53afbd423626650f5 Mon Sep 17 00:00:00 2001 From: Muhammed Teuvazhukov Date: Wed, 7 May 2025 13:46:21 +0300 Subject: [PATCH] fix: Memory leak caused by zombie event listeners in useTouchMove.ts - Use AbortController for all listeners to better readability and scalability --- src/hooks/useTouchMove.ts | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/hooks/useTouchMove.ts b/src/hooks/useTouchMove.ts index f8073ede..f6039524 100644 --- a/src/hooks/useTouchMove.ts +++ b/src/hooks/useTouchMove.ts @@ -110,6 +110,8 @@ export default function useTouchMove( touchEventsRef.current = { onTouchStart, onTouchMove, onTouchEnd, onWheel }; React.useEffect(() => { + const abortController = new AbortController(); + function onProxyTouchStart(e: TouchEvent) { touchEventsRef.current.onTouchStart(e); } @@ -123,16 +125,26 @@ export default function useTouchMove( touchEventsRef.current.onWheel(e); } - document.addEventListener('touchmove', onProxyTouchMove, { passive: false }); - document.addEventListener('touchend', onProxyTouchEnd, { passive: true }); - - // No need to clean up since element removed - ref.current.addEventListener('touchstart', onProxyTouchStart, { passive: true }); - ref.current.addEventListener('wheel', onProxyWheel, { passive: false }); + document.addEventListener('touchmove', onProxyTouchMove, { + passive: false, + signal: abortController.signal, + }); + document.addEventListener('touchend', onProxyTouchEnd, { + passive: true, + signal: abortController.signal, + }); + + ref.current.addEventListener('touchstart', onProxyTouchStart, { + passive: true, + signal: abortController.signal, + }); + ref.current.addEventListener('wheel', onProxyWheel, { + passive: false, + signal: abortController.signal, + }); return () => { - document.removeEventListener('touchmove', onProxyTouchMove); - document.removeEventListener('touchend', onProxyTouchEnd); + abortController.abort(); }; }, []); }