Skip to content

Instantly share code, notes, and snippets.

@ironyee
Forked from sangwonl/useDomSize.ts
Last active March 25, 2022 09:09
Show Gist options
  • Save ironyee/9498659b82e13ddb2d8db3279dafbb9c to your computer and use it in GitHub Desktop.
Save ironyee/9498659b82e13ddb2d8db3279dafbb9c 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 target = ref.current;
if (!target) {
return;
}
const oldSize = lastDomSize.current;
const newSize = {
width: target.clientWidth,
height: target.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