From 49081726256b37e958e8c42b15509462b9302274 Mon Sep 17 00:00:00 2001 From: Leroy Korterink Date: Fri, 9 Feb 2024 11:42:18 +0100 Subject: [PATCH] Memoize resize callback --- src/hooks/useContentRect/useContentRect.ts | 8 +++++--- src/hooks/useContentRectState/useContentRectState.ts | 8 +++++--- src/hooks/useResizeObserver/useResizeObserver.ts | 10 ++++++++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/hooks/useContentRect/useContentRect.ts b/src/hooks/useContentRect/useContentRect.ts index a6718bf..9ca1d17 100644 --- a/src/hooks/useContentRect/useContentRect.ts +++ b/src/hooks/useContentRect/useContentRect.ts @@ -1,4 +1,4 @@ -import { useRef, type RefObject } from 'react'; +import { useRef, type RefObject, useCallback } from 'react'; import { useMount } from '../../lifecycle/hooks/useMount/useMount.js'; import { unref, type Unreffable } from '../../utils/unref/unref.js'; import { useResizeObserver } from '../useResizeObserver/useResizeObserver.js'; @@ -12,9 +12,11 @@ export function useContentRect( ): RefObject { const contentRectRef = useRef(null); - useResizeObserver(target, (entries): void => { + const onResize = useCallback((entries): void => { contentRectRef.current = entries.at(0)?.contentRect ?? null; - }); + }, []); + + useResizeObserver(target, onResize); useMount(() => { contentRectRef.current = unref(target)?.getBoundingClientRect() ?? null; diff --git a/src/hooks/useContentRectState/useContentRectState.ts b/src/hooks/useContentRectState/useContentRectState.ts index aba3ff5..f663073 100644 --- a/src/hooks/useContentRectState/useContentRectState.ts +++ b/src/hooks/useContentRectState/useContentRectState.ts @@ -1,4 +1,4 @@ -import { useRef, useState } from 'react'; +import { useCallback, useRef, useState } from 'react'; import { useMount } from '../../index.js'; import { unref, type Unreffable } from '../../utils/unref/unref.js'; import { useResizeObserver } from '../useResizeObserver/useResizeObserver.js'; @@ -11,12 +11,14 @@ export function useContentRectState(target: Unreffable): DOMRect const [contentRect, setContentRect] = useState(null); const rafRef = useRef(0); - useResizeObserver(target, (entries) => { + const onResize = useCallback((entries) => { cancelAnimationFrame(rafRef.current); rafRef.current = requestAnimationFrame(() => { setContentRect(entries.at(0)?.contentRect ?? null); }); - }); + }, []); + + useResizeObserver(target, onResize); useMount(() => { setContentRect(unref(target)?.getBoundingClientRect() ?? null); diff --git a/src/hooks/useResizeObserver/useResizeObserver.ts b/src/hooks/useResizeObserver/useResizeObserver.ts index e799c52..8800590 100644 --- a/src/hooks/useResizeObserver/useResizeObserver.ts +++ b/src/hooks/useResizeObserver/useResizeObserver.ts @@ -1,5 +1,6 @@ import { useEffect } from 'react'; import { unref, type Unreffable } from '../../utils/unref/unref.js'; +import { useRefValue } from '../useRefValue/useRefValue.js'; /** * This hook allows you to add a ResizeObserver for an element and remove it @@ -14,6 +15,8 @@ export function useResizeObserver( callback?: ResizeObserverCallback | undefined, options?: ResizeObserverOptions, ): void { + const callbackRef = useRefValue(callback); + useEffect(() => { const element = unref(target); @@ -21,12 +24,15 @@ export function useResizeObserver( return; } - const resizeObserver = new ResizeObserver(callback); + const resizeObserver = new ResizeObserver((..._arguments) => { + callbackRef.current?.(..._arguments); + }); + resizeObserver.observe(element, options); return () => { resizeObserver.disconnect(); }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [target, callback, ...Object.values(options ?? {})]); + }, [target, ...Object.values(options ?? {})]); }