import { RefObject, useEffect, useRef } from 'react'; type SizeCallback = (entry: ResizeObserverEntry) => void; type Listener = [el: HTMLElement, cb: SizeCallback]; const listeners: Listener[] = []; let observer: ResizeObserver; export function useSize(ref: RefObject, cb: SizeCallback) { const cbRef = useRef(cb); cbRef.current = cb; const el = ref.current; useEffect(() => { if (el) { if (!observer) { observer = new ResizeObserver((entries) => { // Setting timeout to ensure the callbacks dose not block the currentAnimation frame // will cause ResizeObserver limit exception if callback uses to long time self.setTimeout(() => { for (const entry of entries) { for (const [el, cb] of listeners) { if (entry.target === el) cb(entry); } } }, 10); }); } observer.observe(el); const listener: Listener = [el, (entry) => cbRef.current(entry)]; listeners.push(listener); return () => { observer.unobserve(el); const index = listeners.indexOf(listener); if (index !== -1) listeners.splice(index, 1); }; } }, [el]); }