Skip to content

Instantly share code, notes, and snippets.

@sangwonl
Forked from ironyee/useDomSize.ts
Last active March 25, 2022 09:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sangwonl/af0ffa589f0735cf6797b81ab58ce4dc to your computer and use it in GitHub Desktop.
Save sangwonl/af0ffa589f0735cf6797b81ab58ce4dc to your computer and use it in GitHub Desktop.
import { useCallback, useEffect, useRef, useState } from 'react';
function debounce(callback: Function, delay = 300) {
let handle: number;
return function () {
if (handle) clearTimeout(handle);
handle = setTimeout(callback, delay);
};
}
interface Size {
width: number;
height: number;
}
function isSizeChanged(s1?: Size, s2?: Size) {
if (s1 === s2) {
return false;
}
if (!s1 || !s2) {
return true;
}
return s1.width !== s2.width || s1.height !== s2.height;
}
function useDomSize(onResize: (width: number, height: number) => void) {
const ref = useRef<HTMLDivElement>(null);
const lastDomSize = useRef<Size | undefined>(undefined);
const handleResize = useCallback(() => {
const targetDom = ref.current;
if (!targetDom) {
return;
}
const oldSize = lastDomSize.current;
const newSize = { width: targetDom.clientWidth, height: targetDom.clientHeight };
if (isSizeChanged(oldSize, newSize)) {
onResize(newSize.width, newSize.height);
}
lastDomSize.current = newSize;
}, [onResize]);
useEffect(() => {
handleResize();
const debouncedHandler = debounce(handleResize);
window.addEventListener('resize', debouncedHandler);
return () => window.removeEventListener('resize', debouncedHandler);
}, [handleResize]);
return ref;
}
export default useDomSize;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment