react-resize-detector
Version:
React resize detector
80 lines (77 loc) • 3.65 kB
JavaScript
import { useRef, useState, useCallback, useEffect } from 'react';
import { useCallbackRef, useRefProxy, getDimensions, patchResizeCallback } from './utils.js';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function useResizeDetector({ skipOnMount = false, refreshMode, refreshRate = 1000, refreshOptions, handleWidth = true, handleHeight = true, targetRef, observerOptions, onResize, } = {}) {
// If `skipOnMount` is enabled, skip the first resize event
const skipResize = useRef(skipOnMount);
// Wrap the `onResize` callback with a ref to avoid re-renders
const onResizeRef = useCallbackRef(onResize);
const [size, setSize] = useState({
width: undefined,
height: undefined,
});
// Create a proxy ref to handle conditional rendering and dynamic ref changes of the target element
const { refProxy, refElement } = useRefProxy(targetRef);
const { box } = observerOptions || {};
const resizeCallback = useCallback((entries) => {
if (!handleWidth && !handleHeight)
return;
if (skipResize.current) {
skipResize.current = false;
return;
}
// Only update the size if one of the observed dimensions has changed
const shouldSetSize = (prevSize, nextSize) => (handleWidth && prevSize.width !== nextSize.width) || (handleHeight && prevSize.height !== nextSize.height);
entries.forEach((entry) => {
const dimensions = getDimensions(entry, box);
setSize((prevSize) => {
if (!shouldSetSize(prevSize, dimensions))
return prevSize;
onResizeRef === null || onResizeRef === void 0 ? void 0 : onResizeRef({
width: dimensions.width,
height: dimensions.height,
entry,
});
return dimensions;
});
});
}, [handleWidth, handleHeight, skipResize, box]);
// Throttle/Debounce the resize event if refreshMode is configured
const resizeHandler = useCallback(patchResizeCallback(resizeCallback, refreshMode, refreshRate, refreshOptions), [
resizeCallback,
refreshMode,
refreshRate,
refreshOptions,
]);
// Attach ResizeObserver to the element
useEffect(() => {
let resizeObserver;
if (refElement) {
try {
resizeObserver = new window.ResizeObserver(resizeHandler);
resizeObserver.observe(refElement, observerOptions);
}
catch (error) {
console.warn('ResizeObserver not supported or failed to initialize:', error);
}
}
// If refElement is not available, reset the size
else if (size.width || size.height) {
onResizeRef === null || onResizeRef === void 0 ? void 0 : onResizeRef({
width: null,
height: null,
entry: null,
});
setSize({ width: undefined, height: undefined });
}
// Disconnect the ResizeObserver when the component is unmounted
return () => {
var _a, _b, _c;
(_a = resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect) === null || _a === void 0 ? void 0 : _a.call(resizeObserver);
(_c = (_b = resizeHandler).cancel) === null || _c === void 0 ? void 0 : _c.call(_b);
};
}, [resizeHandler, refElement]);
return Object.assign({ ref: refProxy }, size);
}
export { useResizeDetector as default };
//# sourceMappingURL=useResizeDetector.js.map