Skip to content

Instantly share code, notes, and snippets.

@camflan
Created November 17, 2022 17:18
Show Gist options
  • Save camflan/d8c454aa8312f1b65c1cf39c91eb47fb to your computer and use it in GitHub Desktop.
Save camflan/d8c454aa8312f1b65c1cf39c91eb47fb to your computer and use it in GitHub Desktop.
import { useState, useCallback, useLayoutEffect } from "react";
export interface DimensionObject {
width: number;
height: number;
top: number;
left: number;
x: number;
y: number;
right: number;
bottom: number;
}
export const EmptyElementDimensions: DimensionObject = {
bottom: 0,
height: 0,
left: 0,
right: 0,
top: 0,
width: 0,
x: 0,
y: 0,
};
Object.freeze(EmptyElementDimensions);
export type UseDimensionsHook = [
(node: HTMLElement) => void,
DimensionObject,
HTMLElement | null
];
export interface UseDimensionsArgs {
liveMeasure?: boolean;
}
function getDimensionObject(node: HTMLElement): DimensionObject {
const rect = node.getBoundingClientRect();
return {
width: rect.width,
height: rect.height,
top: "x" in rect ? rect.x : rect.top,
left: "y" in rect ? rect.y : rect.left,
x: "x" in rect ? rect.x : rect.left,
y: "y" in rect ? rect.y : rect.top,
right: rect.right,
bottom: rect.bottom,
};
}
function useDimensions({
liveMeasure = true,
}: UseDimensionsArgs = {}): UseDimensionsHook {
const [dimensions, setDimensions] = useState(EmptyElementDimensions);
const [node, setNode] = useState<null | HTMLElement>(null);
const ref = useCallback((el: HTMLElement) => {
setNode(el);
}, []);
useLayoutEffect(() => {
if (node) {
const measure = () =>
window.requestAnimationFrame(() =>
setDimensions(getDimensionObject(node))
);
measure();
if (liveMeasure) {
window.addEventListener("resize", measure);
window.addEventListener("scroll", measure);
return () => {
window.removeEventListener("resize", measure);
window.removeEventListener("scroll", measure);
};
}
}
return () => {
/* noop */
};
}, [liveMeasure, node]);
return [ref, dimensions, node];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment