Skip to content

Instantly share code, notes, and snippets.

@TrySound
Last active December 6, 2018 19:48
Show Gist options
  • Save TrySound/75c96aad964e8991e37015342c8a643e to your computer and use it in GitHub Desktop.
Save TrySound/75c96aad964e8991e37015342c8a643e to your computer and use it in GitHub Desktop.
// @flow
import * as React from 'react';
import ResizeObserverPolyfill from 'resize-observer-polyfill';
import invariant from 'tiny-invariant';
const useLayoutEffect = (React: any).useLayoutEffect;
const useEffect = (React: any).useEffect;
type Rect = {|
x: number,
y: number,
width: number,
height: number,
|};
const getRect = element => {
const width = element.offsetWidth;
const height = element.offsetHeight;
const rect = element.getBoundingClientRect();
return {
x: rect.left,
y: rect.top,
width,
height,
};
};
export const useMeasure = <T: React.ElementType>(measureRef: {
current: React.ElementRef<T> | null,
}): ?Rect => {
const [rect, setRect] = React.useState<?Rect>(null);
const observer = React.useRef(null);
if (!observer.current) {
observer.current = new ResizeObserverPolyfill(entries => {
const target = entries[0].target;
if (target instanceof HTMLElement) {
setRect(getRect(target));
}
});
}
if (typeof window !== 'undefined') {
useLayoutEffect(() => {
invariant(
measureRef.current instanceof HTMLElement,
'Measuring ref should be an HTMLElement',
);
setRect(getRect(measureRef.current));
}, []);
}
useEffect(() => {
if (measureRef.current instanceof HTMLElement && observer.current) {
observer.current.observe(measureRef.current);
return () => {
if (observer.current) {
observer.current.disconnect();
}
};
}
}, []);
return rect;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment