Skip to content

Commit

Permalink
rect: fix over-rendering and needless attachment of listeners
Browse files Browse the repository at this point in the history
  • Loading branch information
Chance Strickland committed Jun 22, 2020
1 parent 8f07ee5 commit 0df9a02
Showing 1 changed file with 29 additions and 20 deletions.
49 changes: 29 additions & 20 deletions packages/rect/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,43 +91,52 @@ export function useRect<T extends HTMLElement = HTMLElement>(
observe: boolean = true,
onChange?: (rect: DOMRect) => void
): null | DOMRect {
let [element, setElement] = useState(nodeRef.current);
let initialRectSet = useRef(false);
let [rect, setRect] = useState<DOMRect | null>(null);
let observerRef = useRef<any>(null);
let onChangeRef = useRef<typeof onChange>();

useIsomorphicLayoutEffect(() => {
const cleanup = () => {
observerRef.current && observerRef.current.unobserve();
};
onChangeRef.current = onChange;
});

if (!nodeRef.current) {
console.warn("You need to place the ref");
return cleanup;
useIsomorphicLayoutEffect(() => {
if (nodeRef.current !== element) {
setElement(nodeRef.current);
}
});

if (!observerRef.current) {
observerRef.current = observeRect(nodeRef.current, (rect: DOMRect) => {
onChange && onChange(rect);
setRect(rect);
});
useIsomorphicLayoutEffect(() => {
if (element && !initialRectSet.current) {
initialRectSet.current = true;
setRect(element.getBoundingClientRect());
}
}, [element]);

if (!initialRectSet.current) {
initialRectSet.current = true;
setRect(nodeRef.current.getBoundingClientRect());
useIsomorphicLayoutEffect(() => {
if (!element) {
console.warn("You need to place the ref");
return cleanup;
}

observe && observerRef.current.observe();
let observer = observeRect(element, (rect) => {
onChangeRef.current && onChangeRef.current(rect);
setRect(rect);
});

observe && observer.observe();
return cleanup;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [observe, onChange]);

function cleanup() {
observer.unobserve();
}
}, [observe, element]);

return rect;
}

export default Rect;

export type PartialRect = Partial<PRect>;

export type PRect = Partial<DOMRect> & {
readonly bottom: number;
readonly height: number;
Expand Down

0 comments on commit 0df9a02

Please sign in to comment.