From 5ddb995ddfd2c3dd01844d1ccc58713a9994715a Mon Sep 17 00:00:00 2001 From: Maksim Andreev Date: Thu, 31 Oct 2019 20:06:06 +0700 Subject: [PATCH] Use ResizeObserver if supported --- src/index.ts | 25 +++++++++++++++++-------- src/types.d.ts | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/index.ts b/src/index.ts index 5fc60eb..15841b6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,14 +27,23 @@ function useDimensions({ }, []); useLayoutEffect(() => { - if (node) { - const measure = () => - window.requestAnimationFrame(() => - setDimensions(getDimensionObject(node)) - ); - measure(); - - if (liveMeasure) { + if (!node) { + return + } + + const measure = () => + window.requestAnimationFrame(() => + setDimensions(getDimensionObject(node)) + ); + measure(); + + if (liveMeasure) { + if ('ResizeObserver' in window) { + const resizeObserver = new ResizeObserver(measure) + resizeObserver.observe(node) + + return resizeObserver.disconnect + } else { window.addEventListener("resize", measure); window.addEventListener("scroll", measure); diff --git a/src/types.d.ts b/src/types.d.ts index abae2cf..98b32e0 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -18,3 +18,50 @@ export type UseDimensionsHook = [ export interface UseDimensionsArgs { liveMeasure?: boolean; } + +export interface IResizeObserver { + /** + * Adds target to the list of observed elements. + */ + observe: (target: Element) => void + + /** + * Removes target from the list of observed elements. + */ + unobserve: (target: Element) => void + + /** + * Clears both the observationTargets and activeTargets lists. + */ + disconnect: () => void + new (callback: ResizeObserverCallback): this +} + +/** + * This callback delivers ResizeObserver's notifications. It is invoked by a + * broadcast active observations algorithm. + */ +type ResizeObserverCallback = ( + entries: readonly IResizeObserverEntry[], + observer: IResizeObserver +) => void + +interface IResizeObserverEntry { + /** + * The Element whose size has changed. + */ + readonly target: Element + + /** + * Element's content rect when ResizeObserverCallback is invoked. + */ + readonly contentRect: DOMRectReadOnly + /** + * @param target The Element whose size has changed. + */ + new (target: Element): this +} + +declare global { + const ResizeObserver: IResizeObserver +}