diff --git a/.changeset/kind-peas-camp.md b/.changeset/kind-peas-camp.md new file mode 100644 index 0000000000000..14fa679a596ad --- /dev/null +++ b/.changeset/kind-peas-camp.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Reduces web client memory comsumption due to memory leaks diff --git a/apps/meteor/app/analytics/client/loadScript.ts b/apps/meteor/app/analytics/client/loadScript.ts index 32a42cc695c76..e6dc12cd77da0 100644 --- a/apps/meteor/app/analytics/client/loadScript.ts +++ b/apps/meteor/app/analytics/client/loadScript.ts @@ -30,7 +30,7 @@ export const useAnalytics = (): void => { window._paq = window._paq || []; window._paq.push(['setUserId', uid]); } - }); + }, [uid]); useEffect(() => { if (!googleId) { diff --git a/apps/meteor/client/views/room/body/hooks/useListIsAtBottom.ts b/apps/meteor/client/views/room/body/hooks/useListIsAtBottom.ts index 34eb7bc49b106..fc67c50d9fd83 100644 --- a/apps/meteor/client/views/room/body/hooks/useListIsAtBottom.ts +++ b/apps/meteor/client/views/room/body/hooks/useListIsAtBottom.ts @@ -4,6 +4,7 @@ import { useCallback, useRef } from 'react'; import { isAtBottom as isAtBottomLib } from '../../../../../app/ui/client/views/app/lib/scrolling'; import { withThrottling } from '../../../../../lib/utils/highOrderFunctions'; +import { useSafeRefCallback } from '../../../../hooks/useSafeRefCallback'; export const useListIsAtBottom = () => { const atBottomRef = useRef(true); @@ -27,37 +28,42 @@ export const useListIsAtBottom = () => { return isAtBottomLib(innerBoxRef.current, threshold); }, []); - const ref = useCallback( - (node: HTMLElement | null) => { - if (!node) { - return; - } - - const messageList = node.querySelector('ul'); + const ref = useSafeRefCallback( + useCallback( + (node: HTMLElement | null) => { + if (!node) { + return; + } - if (!messageList) { - return; - } + const messageList = node.querySelector('ul'); - const observer = new ResizeObserver(() => { - if (atBottomRef.current === true) { - node.scrollTo({ left: 30, top: node.scrollHeight }); + if (!messageList) { + return; } - }); - observer.observe(messageList); + const observer = new ResizeObserver(() => { + if (atBottomRef.current === true) { + node.scrollTo({ left: 30, top: node.scrollHeight }); + } + }); + + observer.observe(messageList); - node.addEventListener( - 'scroll', - withThrottling({ wait: 100 })(() => { + const handleScroll = withThrottling({ wait: 100 })(() => { atBottomRef.current = isAtBottom(100); - }), - { + }); + + node.addEventListener('scroll', handleScroll, { passive: true, - }, - ); - }, - [isAtBottom], + }); + + return () => { + observer.disconnect(); + node.removeEventListener('scroll', handleScroll); + }; + }, + [isAtBottom], + ), ); return { diff --git a/apps/meteor/client/views/room/hooks/useIsVisible.ts b/apps/meteor/client/views/room/hooks/useIsVisible.ts index 5fec2ce1b1e84..f6afcfdce8987 100644 --- a/apps/meteor/client/views/room/hooks/useIsVisible.ts +++ b/apps/meteor/client/views/room/hooks/useIsVisible.ts @@ -1,23 +1,32 @@ import { useDebouncedState, useSafely } from '@rocket.chat/fuselage-hooks'; import { useCallback } from 'react'; +import { useSafeRefCallback } from '../../../hooks/useSafeRefCallback'; + export const useIsVisible = () => { const [menuVisibility, setMenuVisibility] = useSafely(useDebouncedState(!!window.DISABLE_ANIMATION, 100)); - const callbackRef = useCallback( - (node: HTMLElement | null) => { - if (!node) { - return; - } - const observer = new IntersectionObserver((entries) => { - entries.forEach((entry) => { - setMenuVisibility(entry.isIntersecting); + const callbackRef = useSafeRefCallback( + useCallback( + (node: HTMLElement | null) => { + if (!node) { + return; + } + + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + setMenuVisibility(entry.isIntersecting); + }); }); - }); - observer.observe(node); - }, - [setMenuVisibility], + observer.observe(node); + + return () => { + observer.disconnect(); + }; + }, + [setMenuVisibility], + ), ); return [callbackRef, menuVisibility] as const;