Skip to content

Commit 54bde14

Browse files
committed
[IMPL] useResizeObserver hook
1 parent 06be59f commit 54bde14

7 files changed

Lines changed: 116 additions & 5 deletions

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { useState } from "react";
2+
import { useResizeObserver } from "../../../../../../packages/react-tools/src"
3+
4+
/**
5+
The component renders a textarea element with a ref that receives callback returned from _useResizeObserver__ hook. There are also two button to disconnect and reconnect observer by functions returned from hook.
6+
7+
Hook is initialized with a callback that verifies if textarea element has a width minor or major of 100 px amd set result into __state variable__. The __state variable__ value is displayed on screen.
8+
*/
9+
export const UseResizeObserver = () => {
10+
const [state, setState] = useState(false);
11+
const [refCb, disconnect, reconnect] = useResizeObserver<HTMLTextAreaElement>(
12+
(entries: ResizeObserverEntry[]) => {
13+
const result = entries[0].contentRect.width < 100;
14+
result !== state && setState(result);
15+
});
16+
17+
return <div>
18+
<p>{"Has width < 100 px: " + state}</p>
19+
<textarea ref={refCb} rows={3}></textarea>
20+
<br/>
21+
<button onClick={reconnect}>Reconnect</button>
22+
<button onClick={disconnect}>Disconnect</button>
23+
</div>
24+
}

apps/react-tools-demo/src/constants/components.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ export const COMPONENTS = [
5151
"useResponsive",
5252
"useClickOutside",
5353
"useNetwork",
54-
"useIsOnline"
54+
"useIsOnline",
55+
"useResizeObserver"
5556
],
5657
//API DOM
5758
[
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# useResizeObserver
2+
Hook to use ResizeObserver. Refer to [ResizeObserver API](https://developer.mozilla.org/en-US/docs/Web/API/Resize_Observer_API)
3+
4+
## Usage
5+
6+
```tsx
7+
export const UseResizeObserver = () => {
8+
const refCb = useResizeObserver<HTMLTextAreaElement>((entries: ResizeObserverEntry[]) => { console.log("ciao") });
9+
10+
return <div>
11+
<textarea ref={refCb} rows={3}></textarea>
12+
</div>
13+
}
14+
```
15+
16+
> The component renders a textarea element with a ref that receives callback returned from _useResizeObserver__ hook.
17+
>
18+
> Hook is initialized with....
19+
20+
21+
## API
22+
23+
```tsx
24+
useResizeObserver <T extends Element>(cb: ResizeObserverCallback, opts?: ResizeObserverOptions):RefCallback<T>
25+
```
26+
27+
> ### Params
28+
>
29+
> - __cb__: _ResizeObserverCallback_
30+
> - __opts?__: _ResizeObserverOptions_
31+
>
32+
33+
> ### Returns
34+
>
35+
> __cb for ref component attribute to observe.__
36+
> - _RefCallback<T>_
37+
>

packages/react-tools/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949
- [x] useClickOutside
5050
- [x] useNetwork
5151
- [x] useOnline
52+
- [x] useResizeObserver
53+
- [ ] useIntersectionObserver
54+
- [ ] useMutationObserver
5255
- [ ] useSize (=useMeasuree?)
5356
- [ ] useScrollIntoView
5457
- [ ] useMouse
@@ -57,9 +60,8 @@
5760
- [ ] useOrientation
5861
- [ ] useImageOnLoad
5962
- [ ] usePinchZoom
60-
- [ ] useIntersectionObserver
6163
- [ ] useInViewport (with area ratio of element: check if is equal to useIntersectionObserver)
62-
- [ ] useMutationObserver
64+
- [ ] useIsVisibile (??? check if differ from useInViewport)
6365
- [ ] useInfiniteScroll
6466
- [ ] useDragAndDrop (check for mobile usage)
6567

packages/react-tools/src/hooks/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,5 @@ export { useHover } from './useHover';
4747
export { useResponsive } from './useResponsive';
4848
export { useClickOutside } from './useClickOutside';
4949
export { useNetwork } from './useNetwork';
50-
export { useIsOnline } from './useIsOnline';
50+
export { useIsOnline } from './useIsOnline';
51+
export { useResizeObserver } from './useResizeObserver';
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { RefCallback, useCallback, useRef } from "react"
2+
3+
/**
4+
* **`useResizeObserver`**: Hook to use ResizeObserver. Refer to [ResizeObserver API](https://developer.mozilla.org/en-US/docs/Web/API/Resize_Observer_API)
5+
* @param {ResizeObserverCallback} cb - The function called whenever an observed resize occurs. The function is called with two parameters: __entries__ and __observer__.
6+
* @param {ResizeObserverOptions} [opts] - An options object allowing you to set options for the observation.
7+
* @returns {[RefCallback<T>, ()=>void, ()=>void]} result - array with: cb for ref component attribute to observe, function to _disconnect_ observer, function to _reconnect_ observer.
8+
*/
9+
export const useResizeObserver = <T extends Element>(cb: ResizeObserverCallback, opts?: ResizeObserverOptions):[RefCallback<T>, () => void, () => void] => {
10+
const observer = useRef<ResizeObserver>();
11+
const working = useRef(true);
12+
const nodeRef = useRef<T>();
13+
14+
return [
15+
useCallback((node: T) => {
16+
nodeRef.current = node;
17+
if (!working.current) {
18+
return;
19+
}
20+
if (!node) {
21+
if (observer.current) {
22+
observer.current.disconnect();
23+
observer.current = undefined;
24+
nodeRef.current = undefined;
25+
working.current = true;
26+
}
27+
} else {
28+
observer.current = new ResizeObserver(cb);
29+
observer.current.observe(node, opts);
30+
}
31+
}, [cb, opts]),
32+
useCallback(() => {
33+
if (working.current) {
34+
working.current = false;
35+
!!observer.current && !!nodeRef.current && observer.current.unobserve(nodeRef.current);
36+
}
37+
}, []),
38+
useCallback(() => {
39+
if (!working.current) {
40+
working.current = true;
41+
!!observer.current && !!nodeRef.current && observer.current?.observe(nodeRef.current!, opts)
42+
}
43+
}, [opts])
44+
]
45+
}

packages/react-tools/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ export {
6161
useResponsive,
6262
useClickOutside,
6363
useNetwork,
64-
useIsOnline
64+
useIsOnline,
65+
useResizeObserver
6566
} from './hooks'
6667

6768
export {

0 commit comments

Comments
 (0)