react-resize-detector
Advanced tools
Comparing version 9.0.0 to 9.1.0
@@ -51,3 +51,3 @@ import React,{cloneElement,isValidElement,createRef,PureComponent,Component,forwardRef,useRef,useState,useCallback,useEffect}from'react';import {findDOMNode}from'react-dom';import debounce from'lodash/debounce';import throttle from'lodash/throttle';/*! ***************************************************************************** | ||
return t; | ||
}var patchResizeHandler = function (resizeCallback, refreshMode, refreshRate, refreshOptions) { | ||
}var patchResizeCallback = function (resizeCallback, refreshMode, refreshRate, refreshOptions) { | ||
switch (refreshMode) { | ||
@@ -66,18 +66,2 @@ case 'debounce': | ||
return element instanceof Element || element instanceof HTMLDocument; | ||
}; | ||
var createNotifier = function (setSize, handleWidth, handleHeight) { | ||
return function (_a) { | ||
var width = _a.width, height = _a.height; | ||
setSize(function (prev) { | ||
if (prev.width === width && prev.height === height) { | ||
// skip if dimensions haven't changed | ||
return prev; | ||
} | ||
if ((prev.width === width && !handleHeight) || (prev.height === height && !handleWidth)) { | ||
// process `handleHeight/handleWidth` props | ||
return prev; | ||
} | ||
return { width: width, height: height }; | ||
}); | ||
}; | ||
};var ResizeDetector = /** @class */ (function (_super) { | ||
@@ -150,3 +134,15 @@ __extends(ResizeDetector, _super); | ||
return; | ||
var notifyResize = createNotifier(function (setStateFunc) { return _this.setState(setStateFunc, function () { return onResize === null || onResize === void 0 ? void 0 : onResize(_this.state.width, _this.state.height); }); }, handleWidth, handleHeight); | ||
var notifyResize = function (_a) { | ||
var width = _a.width, height = _a.height; | ||
if (_this.state.width === width && _this.state.height === height) { | ||
// skip if dimensions haven't changed | ||
return; | ||
} | ||
if ((_this.state.width === width && !handleHeight) || (_this.state.height === height && !handleWidth)) { | ||
// process `handleHeight/handleWidth` props | ||
return; | ||
} | ||
onResize === null || onResize === void 0 ? void 0 : onResize(width, height); | ||
_this.setState({ width: width, height: height }); | ||
}; | ||
entries.forEach(function (entry) { | ||
@@ -185,2 +181,5 @@ var _a = (entry && entry.contentRect) || {}, width = _a.width, height = _a.height; | ||
}; | ||
_this.sizeRef = { | ||
current: _this.state | ||
}; | ||
_this.skipOnMount = skipOnMount; | ||
@@ -192,3 +191,3 @@ _this.targetRef = createRef(); | ||
} | ||
_this.resizeHandler = patchResizeHandler(_this.createResizeHandler, refreshMode, refreshRate, refreshOptions); | ||
_this.resizeHandler = patchResizeCallback(_this.createResizeHandler, refreshMode, refreshRate, refreshOptions); | ||
_this.resizeObserver = new window.ResizeObserver(_this.resizeHandler); | ||
@@ -202,2 +201,3 @@ return _this; | ||
this.attachObserver(); | ||
this.sizeRef.current = this.state; | ||
}; | ||
@@ -290,9 +290,12 @@ ResizeDetector.prototype.componentWillUnmount = function () { | ||
var onRefChange = useCallback(function (node) { | ||
setRefElement(node); | ||
}, []); | ||
if (node !== refElement) { | ||
setRefElement(node); | ||
} | ||
}, [refElement]); | ||
// adding `current` to make it compatible with useRef shape | ||
onRefChange.current = refElement; | ||
var resizeHandler = useRef(); | ||
useEffect(function () { | ||
return function () { | ||
// component is unmounted | ||
// clear ref to avoid memory leaks | ||
setRefElement(null); | ||
@@ -302,33 +305,54 @@ onRefChange.current = null; | ||
}, []); | ||
useEffect(function () { | ||
var shouldSetSize = useCallback(function (prevSize, nextSize) { | ||
if (prevSize.width === nextSize.width && prevSize.height === nextSize.height) { | ||
// skip if dimensions haven't changed | ||
return false; | ||
} | ||
if ((prevSize.width === nextSize.width && !handleHeight) || | ||
(prevSize.height === nextSize.height && !handleWidth)) { | ||
// process `handleHeight/handleWidth` props | ||
return false; | ||
} | ||
return true; | ||
}, [handleWidth, handleHeight]); | ||
var resizeCallback = useCallback(function (entries) { | ||
if (!handleWidth && !handleHeight) | ||
return; | ||
if (!refElement && (size.width || size.height)) { | ||
setSize({ width: undefined, height: undefined }); | ||
if (skipResize.current) { | ||
skipResize.current = false; | ||
return; | ||
} | ||
var notifyResize = createNotifier(setSize, handleWidth, handleHeight); | ||
var resizeCallback = function (entries) { | ||
if (!handleWidth && !handleHeight) | ||
return; | ||
entries.forEach(function (entry) { | ||
var _a = (entry && entry.contentRect) || {}, width = _a.width, height = _a.height; | ||
var shouldSetSize = !skipResize.current; | ||
if (shouldSetSize) { | ||
notifyResize({ width: width, height: height }); | ||
} | ||
skipResize.current = false; | ||
entries.forEach(function (entry) { | ||
var _a = (entry === null || entry === void 0 ? void 0 : entry.contentRect) || {}, width = _a.width, height = _a.height; | ||
setSize(function (prevSize) { | ||
if (!shouldSetSize(prevSize, { width: width, height: height })) | ||
return prevSize; | ||
return { width: width, height: height }; | ||
}); | ||
}; | ||
resizeHandler.current = patchResizeHandler(resizeCallback, refreshMode, refreshRate, refreshOptions); | ||
var resizeObserver = new window.ResizeObserver(resizeHandler.current); | ||
}); | ||
}, [handleWidth, handleHeight, skipResize, shouldSetSize]); | ||
var resizeHandler = useCallback(patchResizeCallback(resizeCallback, refreshMode, refreshRate, refreshOptions), [ | ||
resizeCallback, | ||
refreshMode, | ||
refreshRate, | ||
refreshOptions | ||
]); | ||
// on refElement change | ||
useEffect(function () { | ||
var resizeObserver; | ||
if (refElement) { | ||
resizeObserver = new window.ResizeObserver(resizeHandler); | ||
resizeObserver.observe(refElement, observerOptions); | ||
} | ||
else { | ||
if (size.width || size.height) { | ||
setSize({ width: undefined, height: undefined }); | ||
} | ||
} | ||
return function () { | ||
var _a, _b; | ||
resizeObserver.disconnect(); | ||
(_b = (_a = resizeHandler.current).cancel) === null || _b === void 0 ? void 0 : _b.call(_a); | ||
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); | ||
}; | ||
}, [refreshMode, refreshRate, refreshOptions, handleWidth, handleHeight, observerOptions, refElement]); | ||
}, [resizeHandler, refElement]); | ||
useEffect(function () { | ||
@@ -335,0 +359,0 @@ onResize === null || onResize === void 0 ? void 0 : onResize(size.width, size.height); |
@@ -51,3 +51,3 @@ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var React=require('react'),reactDom=require('react-dom'),debounce=require('lodash/debounce'),throttle=require('lodash/throttle');/*! ***************************************************************************** | ||
return t; | ||
}var patchResizeHandler = function (resizeCallback, refreshMode, refreshRate, refreshOptions) { | ||
}var patchResizeCallback = function (resizeCallback, refreshMode, refreshRate, refreshOptions) { | ||
switch (refreshMode) { | ||
@@ -66,18 +66,2 @@ case 'debounce': | ||
return element instanceof Element || element instanceof HTMLDocument; | ||
}; | ||
var createNotifier = function (setSize, handleWidth, handleHeight) { | ||
return function (_a) { | ||
var width = _a.width, height = _a.height; | ||
setSize(function (prev) { | ||
if (prev.width === width && prev.height === height) { | ||
// skip if dimensions haven't changed | ||
return prev; | ||
} | ||
if ((prev.width === width && !handleHeight) || (prev.height === height && !handleWidth)) { | ||
// process `handleHeight/handleWidth` props | ||
return prev; | ||
} | ||
return { width: width, height: height }; | ||
}); | ||
}; | ||
};var ResizeDetector = /** @class */ (function (_super) { | ||
@@ -150,3 +134,15 @@ __extends(ResizeDetector, _super); | ||
return; | ||
var notifyResize = createNotifier(function (setStateFunc) { return _this.setState(setStateFunc, function () { return onResize === null || onResize === void 0 ? void 0 : onResize(_this.state.width, _this.state.height); }); }, handleWidth, handleHeight); | ||
var notifyResize = function (_a) { | ||
var width = _a.width, height = _a.height; | ||
if (_this.state.width === width && _this.state.height === height) { | ||
// skip if dimensions haven't changed | ||
return; | ||
} | ||
if ((_this.state.width === width && !handleHeight) || (_this.state.height === height && !handleWidth)) { | ||
// process `handleHeight/handleWidth` props | ||
return; | ||
} | ||
onResize === null || onResize === void 0 ? void 0 : onResize(width, height); | ||
_this.setState({ width: width, height: height }); | ||
}; | ||
entries.forEach(function (entry) { | ||
@@ -185,2 +181,5 @@ var _a = (entry && entry.contentRect) || {}, width = _a.width, height = _a.height; | ||
}; | ||
_this.sizeRef = { | ||
current: _this.state | ||
}; | ||
_this.skipOnMount = skipOnMount; | ||
@@ -192,3 +191,3 @@ _this.targetRef = React.createRef(); | ||
} | ||
_this.resizeHandler = patchResizeHandler(_this.createResizeHandler, refreshMode, refreshRate, refreshOptions); | ||
_this.resizeHandler = patchResizeCallback(_this.createResizeHandler, refreshMode, refreshRate, refreshOptions); | ||
_this.resizeObserver = new window.ResizeObserver(_this.resizeHandler); | ||
@@ -202,2 +201,3 @@ return _this; | ||
this.attachObserver(); | ||
this.sizeRef.current = this.state; | ||
}; | ||
@@ -290,9 +290,12 @@ ResizeDetector.prototype.componentWillUnmount = function () { | ||
var onRefChange = React.useCallback(function (node) { | ||
setRefElement(node); | ||
}, []); | ||
if (node !== refElement) { | ||
setRefElement(node); | ||
} | ||
}, [refElement]); | ||
// adding `current` to make it compatible with useRef shape | ||
onRefChange.current = refElement; | ||
var resizeHandler = React.useRef(); | ||
React.useEffect(function () { | ||
return function () { | ||
// component is unmounted | ||
// clear ref to avoid memory leaks | ||
setRefElement(null); | ||
@@ -302,33 +305,54 @@ onRefChange.current = null; | ||
}, []); | ||
React.useEffect(function () { | ||
var shouldSetSize = React.useCallback(function (prevSize, nextSize) { | ||
if (prevSize.width === nextSize.width && prevSize.height === nextSize.height) { | ||
// skip if dimensions haven't changed | ||
return false; | ||
} | ||
if ((prevSize.width === nextSize.width && !handleHeight) || | ||
(prevSize.height === nextSize.height && !handleWidth)) { | ||
// process `handleHeight/handleWidth` props | ||
return false; | ||
} | ||
return true; | ||
}, [handleWidth, handleHeight]); | ||
var resizeCallback = React.useCallback(function (entries) { | ||
if (!handleWidth && !handleHeight) | ||
return; | ||
if (!refElement && (size.width || size.height)) { | ||
setSize({ width: undefined, height: undefined }); | ||
if (skipResize.current) { | ||
skipResize.current = false; | ||
return; | ||
} | ||
var notifyResize = createNotifier(setSize, handleWidth, handleHeight); | ||
var resizeCallback = function (entries) { | ||
if (!handleWidth && !handleHeight) | ||
return; | ||
entries.forEach(function (entry) { | ||
var _a = (entry && entry.contentRect) || {}, width = _a.width, height = _a.height; | ||
var shouldSetSize = !skipResize.current; | ||
if (shouldSetSize) { | ||
notifyResize({ width: width, height: height }); | ||
} | ||
skipResize.current = false; | ||
entries.forEach(function (entry) { | ||
var _a = (entry === null || entry === void 0 ? void 0 : entry.contentRect) || {}, width = _a.width, height = _a.height; | ||
setSize(function (prevSize) { | ||
if (!shouldSetSize(prevSize, { width: width, height: height })) | ||
return prevSize; | ||
return { width: width, height: height }; | ||
}); | ||
}; | ||
resizeHandler.current = patchResizeHandler(resizeCallback, refreshMode, refreshRate, refreshOptions); | ||
var resizeObserver = new window.ResizeObserver(resizeHandler.current); | ||
}); | ||
}, [handleWidth, handleHeight, skipResize, shouldSetSize]); | ||
var resizeHandler = React.useCallback(patchResizeCallback(resizeCallback, refreshMode, refreshRate, refreshOptions), [ | ||
resizeCallback, | ||
refreshMode, | ||
refreshRate, | ||
refreshOptions | ||
]); | ||
// on refElement change | ||
React.useEffect(function () { | ||
var resizeObserver; | ||
if (refElement) { | ||
resizeObserver = new window.ResizeObserver(resizeHandler); | ||
resizeObserver.observe(refElement, observerOptions); | ||
} | ||
else { | ||
if (size.width || size.height) { | ||
setSize({ width: undefined, height: undefined }); | ||
} | ||
} | ||
return function () { | ||
var _a, _b; | ||
resizeObserver.disconnect(); | ||
(_b = (_a = resizeHandler.current).cancel) === null || _b === void 0 ? void 0 : _b.call(_a); | ||
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); | ||
}; | ||
}, [refreshMode, refreshRate, refreshOptions, handleWidth, handleHeight, observerOptions, refElement]); | ||
}, [resizeHandler, refElement]); | ||
React.useEffect(function () { | ||
@@ -335,0 +359,0 @@ onResize === null || onResize === void 0 ? void 0 : onResize(size.width, size.height); |
@@ -9,2 +9,6 @@ import React, { PureComponent } from 'react'; | ||
resizeObserver: any; | ||
/** | ||
* To access the current size in the ResizeObserver without having to recreate it each time size updates. | ||
*/ | ||
private readonly sizeRef; | ||
constructor(props: ResizeDetectorProps<ElementT>); | ||
@@ -11,0 +15,0 @@ componentDidMount(): void; |
import type { DebouncedFunc } from 'lodash'; | ||
import { Props, ReactResizeDetectorDimensions } from './types'; | ||
import { Props } from './types'; | ||
export type PatchedResizeObserverCallback = DebouncedFunc<ResizeObserverCallback> | ResizeObserverCallback; | ||
export declare const patchResizeHandler: (resizeCallback: ResizeObserverCallback, refreshMode: Props['refreshMode'], refreshRate: Props['refreshRate'], refreshOptions: Props['refreshOptions']) => PatchedResizeObserverCallback; | ||
export declare const patchResizeCallback: (resizeCallback: ResizeObserverCallback, refreshMode: Props['refreshMode'], refreshRate: Props['refreshRate'], refreshOptions: Props['refreshOptions']) => PatchedResizeObserverCallback; | ||
export declare const isFunction: (fn: unknown) => boolean; | ||
export declare const isSSR: () => boolean; | ||
export declare const isDOMElement: (element: unknown) => boolean; | ||
export declare const createNotifier: (setSize: React.Dispatch<React.SetStateAction<ReactResizeDetectorDimensions>>, handleWidth: boolean, handleHeight: boolean) => ({ width, height }: ReactResizeDetectorDimensions) => void; |
{ | ||
"name": "react-resize-detector", | ||
"version": "9.0.0", | ||
"version": "9.1.0", | ||
"description": "React resize detector", | ||
@@ -5,0 +5,0 @@ "main": "build/index.js", |
@@ -69,3 +69,3 @@ # Handle element resizes like it's 2023! | ||
```jsx | ||
import ResizeObserver from 'react-resize-detector'; | ||
import { useResizeDetector } from 'react-resize-detector'; | ||
``` | ||
@@ -75,6 +75,4 @@ | ||
Starting from v6.0.0 there are 3 recommended ways to work with `resize-detector` library: | ||
#### 1. React hook | ||
#### 1. React hook (new in v6.0.0) | ||
```jsx | ||
@@ -112,3 +110,3 @@ import { useResizeDetector } from 'react-resize-detector'; | ||
<details><summary>With custom ref</summary> | ||
<details><summary>With custom ref. _not recommended, may have some unexpected behaviour if you dynamically mount/unmount the observed element_</summary> | ||
@@ -243,26 +241,2 @@ ```js | ||
## Performance optimization | ||
This library uses the native [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) API. | ||
DOM nodes get attached to `ResizeObserver.observe` every time the component mounts and every time any property gets changed. | ||
It means you should try to avoid passing anonymous functions to `ResizeDetector`, because they will trigger the whole initialization process every time the component rerenders. Use `useCallback` whenever it's possible. | ||
```jsx | ||
// WRONG - anonymous function | ||
const { ref, width, height } = useResizeDetector({ | ||
onResize: () => { | ||
// on resize logic | ||
} | ||
}); | ||
// CORRECT - `useCallback` approach | ||
const onResize = useCallback(() => { | ||
// on resize logic | ||
}, []); | ||
const { ref, width, height } = useResizeDetector({ onResize }); | ||
``` | ||
## Refs | ||
@@ -269,0 +243,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
131428
860
321