Skip to content

Commit 508d041

Browse files
feat(react-measure): Replace react-measure with resizeObserver (#285)
1 parent aad57e0 commit 508d041

File tree

3 files changed

+43
-74
lines changed

3 files changed

+43
-74
lines changed

packages/module/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,12 @@
3838
"@patternfly/react-styles": "^6.0.0",
3939
"@types/d3": "^7.4.0",
4040
"@types/d3-force": "^1.2.1",
41-
"@types/react-measure": "^2.0.6",
4241
"d3": "^7.8.0",
4342
"@dagrejs/dagre": "1.1.2",
4443
"mobx": "^6.9.0",
4544
"mobx-react": "^7.6.0",
4645
"point-in-svg-path": "^1.0.1",
4746
"popper.js": "^1.16.1",
48-
"react-measure": "^2.3.0",
4947
"tslib": "^2.0.0",
5048
"webcola": "3.4.0"
5149
},

packages/module/src/components/VisualizationSurface.tsx

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { useRef, useCallback, useEffect, useMemo } from 'react';
1+
import { FunctionComponent, MouseEvent as ReactMouseEvent, ReactNode, useRef, useCallback, useEffect } from 'react';
22
import { action } from 'mobx';
33
// https://github.com/mobxjs/mobx-react#observer-batching
44
import 'mobx-react/batchingForReactDom';
55
import { observer } from 'mobx-react';
6-
import ReactMeasure, { ContentRect } from 'react-measure';
6+
import { debounce, getResizeObserver } from '@patternfly/react-core';
77
import { css } from '@patternfly/react-styles';
88
import styles from '../css/topology-components';
99
import { State } from '../types';
@@ -16,72 +16,70 @@ interface VisualizationSurfaceProps {
1616
/** State to be passed to the controller */
1717
state?: State;
1818
/** Additional content rendered inside the surface */
19-
children?: React.ReactNode;
19+
children?: ReactNode;
2020
}
2121

22-
const stopEvent = (e: React.MouseEvent): void => {
22+
const stopEvent = (e: ReactMouseEvent): void => {
2323
e.preventDefault();
2424
e.stopPropagation();
2525
};
2626

27-
const VisualizationSurface: React.FunctionComponent<VisualizationSurfaceProps> = ({
28-
state
29-
}: VisualizationSurfaceProps) => {
27+
const VisualizationSurface: FunctionComponent<VisualizationSurfaceProps> = ({ state }: VisualizationSurfaceProps) => {
3028
const controller = useVisualizationController();
31-
const timerId = useRef<NodeJS.Timeout>(null);
29+
const unObserver = useRef<() => void>(null);
3230

33-
const debounceMeasure = useCallback((func: (contentRect: ContentRect) => void, delay?: number) => {
34-
return (contentRect: ContentRect) => {
35-
if (!timerId.current) {
36-
func(contentRect);
31+
const measureRef = useCallback(
32+
(ref: HTMLDivElement) => {
33+
// Remove any previous observer
34+
if (unObserver.current) {
35+
unObserver.current();
3736
}
38-
clearTimeout(timerId.current);
3937

40-
timerId.current = setTimeout(() => func(contentRect), delay);
38+
if (!ref) {
39+
return;
40+
}
41+
42+
const handleResize = action(() =>
43+
controller.getGraph().setDimensions(new Dimensions(ref.clientWidth, ref.clientHeight))
44+
);
45+
46+
// Set size on initialization
47+
handleResize();
48+
49+
const debounceResize = debounce(handleResize, 100);
50+
51+
// Update graph size on resize events
52+
unObserver.current = getResizeObserver(ref, debounceResize);
53+
},
54+
[controller]
55+
);
56+
57+
useEffect(() => {
58+
return () => {
59+
if (unObserver.current) {
60+
unObserver.current();
61+
}
4162
};
4263
}, []);
4364

4465
useEffect(() => {
4566
state && controller.setState(state);
4667
}, [controller, state]);
4768

48-
const onMeasure = useMemo(
49-
() =>
50-
debounceMeasure(
51-
action((contentRect: ContentRect) => {
52-
controller.getGraph().setDimensions(new Dimensions(contentRect.client.width, contentRect.client.height));
53-
}),
54-
100
55-
),
56-
[controller, debounceMeasure]
57-
);
58-
59-
// dispose of onMeasure
60-
useEffect(() => () => clearTimeout(timerId.current), [onMeasure]);
61-
6269
if (!controller.hasGraph()) {
6370
return null;
6471
}
6572

6673
const graph = controller.getGraph();
6774

68-
// TODO: We need to replace react-measure as it doesn't support React 19. The following
69-
// casting helps to get topology to build with React 19 versions
70-
const Wrapper = ReactMeasure as any;
71-
7275
return (
73-
<Wrapper client onResize={onMeasure}>
74-
{({ measureRef }: { measureRef: React.LegacyRef<any> }) => (
75-
<div data-test-id="topology" className={css(styles.topologyVisualizationSurface)} ref={measureRef}>
76-
{/* render an outer div because react-measure doesn't seem to fire events properly on svg resize */}
77-
<svg className={css(styles.topologyVisualizationSurfaceSvg)} onContextMenu={stopEvent}>
78-
<SVGDefsProvider>
79-
<ElementWrapper element={graph} />
80-
</SVGDefsProvider>
81-
</svg>
82-
</div>
83-
)}
84-
</Wrapper>
76+
<div data-test-id="topology" className={css(styles.topologyVisualizationSurface)} ref={measureRef}>
77+
<svg className={css(styles.topologyVisualizationSurfaceSvg)} onContextMenu={stopEvent}>
78+
<SVGDefsProvider>
79+
<ElementWrapper element={graph} />
80+
</SVGDefsProvider>
81+
</svg>
82+
</div>
8583
);
8684
};
8785

yarn.lock

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,7 +1979,7 @@
19791979
resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
19801980
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
19811981

1982-
"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.2.0":
1982+
"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.13":
19831983
version "7.20.13"
19841984
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz"
19851985
integrity sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==
@@ -3403,13 +3403,6 @@
34033403
dependencies:
34043404
"@types/react" "*"
34053405

3406-
"@types/react-measure@^2.0.6":
3407-
version "2.0.8"
3408-
resolved "https://registry.npmjs.org/@types/react-measure/-/react-measure-2.0.8.tgz"
3409-
integrity sha512-Pu4/hQ/1AKVN6efoawtcM+l376WYOI8e1fiM6ir4pdLkHilDCkJLjUGvAm0mWKJ0GE6hzu55yCrcJ/xNyEdFwA==
3410-
dependencies:
3411-
"@types/react" "*"
3412-
34133406
"@types/react-router-dom@^5.3.3":
34143407
version "5.3.3"
34153408
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83"
@@ -8007,11 +8000,6 @@ get-intrinsic@^1.2.4:
80078000
has-symbols "^1.0.3"
80088001
hasown "^2.0.0"
80098002

8010-
get-node-dimensions@^1.2.1:
8011-
version "1.2.1"
8012-
resolved "https://registry.npmjs.org/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz"
8013-
integrity sha512-2MSPMu7S1iOTL+BOa6K1S62hB2zUAYNF/lV0gSVlOaacd087lc6nR1H1r0e3B1CerTo+RceOmi1iJW+vp21xcQ==
8014-
80158003
get-package-type@^0.1.0:
80168004
version "0.1.0"
80178005
resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz"
@@ -12384,16 +12372,6 @@ react-lifecycles-compat@^3.0.4:
1238412372
resolved "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz"
1238512373
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
1238612374

12387-
react-measure@^2.3.0:
12388-
version "2.5.2"
12389-
resolved "https://registry.npmjs.org/react-measure/-/react-measure-2.5.2.tgz"
12390-
integrity sha512-M+rpbTLWJ3FD6FXvYV6YEGvQ5tMayQ3fGrZhRPHrE9bVlBYfDCLuDcgNttYfk8IqfOI03jz6cbpqMRTUclQnaA==
12391-
dependencies:
12392-
"@babel/runtime" "^7.2.0"
12393-
get-node-dimensions "^1.2.1"
12394-
prop-types "^15.6.2"
12395-
resize-observer-polyfill "^1.5.0"
12396-
1239712375
react-monaco-editor@^0.51.0:
1239812376
version "0.51.0"
1239912377
resolved "https://registry.yarnpkg.com/react-monaco-editor/-/react-monaco-editor-0.51.0.tgz#68d6afc912f7fcb7782e57b39889a5fd75fc0ceb"
@@ -12859,11 +12837,6 @@ requires-port@^1.0.0:
1285912837
resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz"
1286012838
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
1286112839

12862-
resize-observer-polyfill@^1.5.0:
12863-
version "1.5.1"
12864-
resolved "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz"
12865-
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
12866-
1286712840
resolve-cwd@^3.0.0:
1286812841
version "3.0.0"
1286912842
resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz"

0 commit comments

Comments
 (0)