Resize observer for React that provides a declarative interface for monitoring DOM element size changes
npx @tessl/cli install tessl/npm-rc-resize-observer@1.4.0RC Resize Observer is a React component library that provides a declarative interface for monitoring DOM element size changes using the ResizeObserver API. It includes automatic fallback to polyfill for browser compatibility and offers both individual element observation and batch collection for multiple elements.
npm install rc-resize-observerimport ResizeObserver from "rc-resize-observer";
import { _rs } from "rc-resize-observer"; // Test utility onlyFor CommonJS:
const ResizeObserver = require("rc-resize-observer");
const { _rs } = require("rc-resize-observer"); // Test utility onlyimport ResizeObserver from "rc-resize-observer";
// Basic resize observation
<ResizeObserver onResize={(size, element) => console.log(size)}>
<div>Content to observe</div>
</ResizeObserver>
// Collection for multiple elements
<ResizeObserver.Collection onBatchResize={(resizeInfos) => console.log(resizeInfos)}>
<ResizeObserver><div>Item 1</div></ResizeObserver>
<ResizeObserver><div>Item 2</div></ResizeObserver>
</ResizeObserver.Collection>
// Render props pattern
<ResizeObserver onResize={(size) => console.log(size)}>
{(ref) => <div ref={ref}>Content</div>}
</ResizeObserver>RC Resize Observer is built around several key components:
Main component for monitoring individual element size changes with React-friendly API.
interface ResizeObserverProps {
/** Pass to ResizeObserver.Collection with additional data */
data?: any;
children: React.ReactNode | ((ref: React.RefObject<any>) => React.ReactElement);
disabled?: boolean;
/** Trigger if element resized. Will always trigger when first time render. */
onResize?: OnResize;
}
type OnResize = (size: SizeInfo, element: HTMLElement) => void;
interface SizeInfo {
width: number;
height: number;
offsetWidth: number;
offsetHeight: number;
}
declare const ResizeObserver: React.ForwardRefExoticComponent<
React.PropsWithoutRef<ResizeObserverProps> & React.RefAttributes<any>
> & {
Collection: typeof Collection;
};
/** @private Test only for mock trigger resize event */
export declare const _rs: (entities: ResizeObserverEntry[]) => void;Usage Examples:
import ResizeObserver from "rc-resize-observer";
// Simple observation
<ResizeObserver onResize={(size, element) => {
console.log(`Element resized to ${size.width}x${size.height}`);
}}>
<textarea placeholder="Resize me" />
</ResizeObserver>
// With disabled state
import { useState } from "react";
const [disabled, setDisabled] = useState(false);
<ResizeObserver
disabled={disabled}
onResize={(size) => console.log('Resized:', size)}
>
<div>Conditional observation</div>
</ResizeObserver>
// Render props for ref control
<ResizeObserver onResize={(size) => console.log(size)}>
{(ref) => <canvas ref={ref} width={400} height={300} />}
</ResizeObserver>
// Forward ref access
import { useRef } from "react";
const observerRef = useRef<HTMLElement>(null);
<ResizeObserver ref={observerRef} onResize={handleResize}>
<div>Referable element</div>
</ResizeObserver>Collects resize events from multiple ResizeObserver children and batches them into a single callback for efficient handling.
interface CollectionProps {
/** Trigger when some children ResizeObserver changed. Collect by frame render level */
onBatchResize?: (resizeInfo: ResizeInfo[]) => void;
children?: React.ReactNode;
}
interface ResizeInfo {
size: SizeInfo;
data: any;
element: HTMLElement;
}
declare function Collection(props: CollectionProps): React.ReactElement;Usage Examples:
import ResizeObserver from "rc-resize-observer";
// Batch multiple resize events
<ResizeObserver.Collection
onBatchResize={(resizeInfos) => {
console.log(`${resizeInfos.length} elements resized`);
resizeInfos.forEach(({ size, element, data }) => {
console.log(`Element ${data.id}: ${size.width}x${size.height}`);
});
}}
>
<ResizeObserver data={{ id: 'panel1' }}>
<div>Panel 1</div>
</ResizeObserver>
<ResizeObserver data={{ id: 'panel2' }}>
<div>Panel 2</div>
</ResizeObserver>
<ResizeObserver data={{ id: 'panel3' }}>
<div>Panel 3</div>
</ResizeObserver>
</ResizeObserver.Collection>
// Nested collections
<ResizeObserver.Collection onBatchResize={handleOuterBatch}>
<ResizeObserver.Collection onBatchResize={handleInnerBatch}>
<ResizeObserver><div>Nested item</div></ResizeObserver>
</ResizeObserver.Collection>
<ResizeObserver><div>Outer item</div></ResizeObserver>
</ResizeObserver.Collection>Provides context for collection-level resize events.
type onCollectionResize = (size: SizeInfo, element: HTMLElement, data: any) => void;
declare const CollectionContext: React.Context<onCollectionResize>;Low-level observation utilities used internally.
type ResizeListener = (element: Element) => void;
/**
* Register a resize listener for an element
* @param element - DOM element to observe
* @param callback - Callback function to call on resize
*/
declare function observe(element: Element, callback: ResizeListener): void;
/**
* Unregister a resize listener for an element
* @param element - DOM element to stop observing
* @param callback - Callback function to remove
*/
declare function unobserve(element: Element, callback: ResizeListener): void;interface SizeInfo {
width: number;
height: number;
offsetWidth: number;
offsetHeight: number;
}
type OnResize = (size: SizeInfo, element: HTMLElement) => void;
type ResizeListener = (element: Element) => void;
type onCollectionResize = (size: SizeInfo, element: HTMLElement, data: any) => void;interface ResizeObserverProps {
/** Pass to ResizeObserver.Collection with additional data */
data?: any;
children: React.ReactNode | ((ref: React.RefObject<any>) => React.ReactElement);
disabled?: boolean;
/** Trigger if element resized. Will always trigger when first time render. */
onResize?: OnResize;
}
interface SingleObserverProps extends ResizeObserverProps {
children: React.ReactElement | ((ref: React.RefObject<Element>) => React.ReactElement);
}
interface CollectionProps {
/** Trigger when some children ResizeObserver changed. Collect by frame render level */
onBatchResize?: (resizeInfo: ResizeInfo[]) => void;
children?: React.ReactNode;
}
interface ResizeInfo {
size: SizeInfo;
data: any;
element: HTMLElement;
}RC Resize Observer includes built-in development warnings:
RC Resize Observer exports a test utility for mocking resize events in test environments.
/** @private Test only for mock trigger resize event */
declare const _rs: (entities: ResizeObserverEntry[]) => void;Usage in Tests:
import { _rs } from "rc-resize-observer";
// Mock resize event for testing
const mockEntry = {
target: document.querySelector('.test-element'),
contentRect: { width: 100, height: 50 },
borderBoxSize: [{ inlineSize: 100, blockSize: 50 }],
contentBoxSize: [{ inlineSize: 100, blockSize: 50 }],
devicePixelContentBoxSize: [{ inlineSize: 100, blockSize: 50 }]
} as ResizeObserverEntry;
_rs([mockEntry]);RC Resize Observer uses resize-observer-polyfill for automatic fallback support in browsers that don't natively support the ResizeObserver API. No additional configuration is required - the polyfill is automatically used when needed.