Skip to content

Commit 0e84c43

Browse files
committed
chore: refactor
1 parent 9cf4344 commit 0e84c43

File tree

2 files changed

+88
-84
lines changed

2 files changed

+88
-84
lines changed

src/SingleObserver/index.tsx

Lines changed: 13 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import { getDOM } from '@rc-component/util/lib/Dom/findDOMNode';
22
import { supportRef, useComposeRef, getNodeRef } from '@rc-component/util/lib/ref';
33
import * as React from 'react';
4-
import type { ResizeObserverProps } from '..';
4+
import type { ResizeObserverProps, SizeInfo } from '..';
55
import { CollectionContext } from '../Collection';
6-
import { observe, unobserve } from '../utils/observerUtil';
6+
import useResizeObserver from '../useResizeObserver';
77

88
export interface SingleObserverProps extends ResizeObserverProps {
99
children: React.ReactElement | ((ref: React.RefObject<Element>) => React.ReactElement);
1010
}
1111

1212
function SingleObserver(props: SingleObserverProps, ref: React.Ref<HTMLElement>) {
13-
const { children, disabled } = props;
13+
const { children, disabled, onResize, data } = props;
1414
const elementRef = React.useRef<Element>(null);
1515

1616
const onCollectionResize = React.useContext(CollectionContext);
@@ -19,14 +19,6 @@ function SingleObserver(props: SingleObserverProps, ref: React.Ref<HTMLElement>)
1919
const isRenderProps = typeof children === 'function';
2020
const mergedChildren = isRenderProps ? children(elementRef) : children;
2121

22-
// ============================= Size =============================
23-
const sizeRef = React.useRef({
24-
width: -1,
25-
height: -1,
26-
offsetWidth: -1,
27-
offsetHeight: -1,
28-
});
29-
3022
// ============================= Ref ==============================
3123
const canRef =
3224
!isRenderProps && React.isValidElement(mergedChildren) && supportRef(mergedChildren);
@@ -35,81 +27,22 @@ function SingleObserver(props: SingleObserverProps, ref: React.Ref<HTMLElement>)
3527
const mergedRef = useComposeRef(originRef, elementRef);
3628

3729
const getDomElement = () => {
38-
return getDOM( elementRef.current ) as HTMLElement
39-
}
40-
30+
return getDOM(elementRef.current) as HTMLElement;
31+
};
4132

4233
React.useImperativeHandle(ref, () => getDomElement());
4334

4435
// =========================== Observe ============================
45-
const propsRef = React.useRef<SingleObserverProps>(props);
46-
propsRef.current = props;
47-
48-
// Handler
49-
const onInternalResize = React.useCallback((target: HTMLElement) => {
50-
const { onResize, data } = propsRef.current;
51-
52-
const { width, height } = target.getBoundingClientRect();
53-
const { offsetWidth, offsetHeight } = target;
54-
55-
/**
56-
* Resize observer trigger when content size changed.
57-
* In most case we just care about element size,
58-
* let's use `boundary` instead of `contentRect` here to avoid shaking.
59-
*/
60-
const fixedWidth = Math.floor(width);
61-
const fixedHeight = Math.floor(height);
62-
63-
if (
64-
sizeRef.current.width !== fixedWidth ||
65-
sizeRef.current.height !== fixedHeight ||
66-
sizeRef.current.offsetWidth !== offsetWidth ||
67-
sizeRef.current.offsetHeight !== offsetHeight
68-
) {
69-
const size = { width: fixedWidth, height: fixedHeight, offsetWidth, offsetHeight };
70-
sizeRef.current = size;
71-
72-
// IE is strange, right?
73-
const mergedOffsetWidth = offsetWidth === Math.round(width) ? width : offsetWidth;
74-
const mergedOffsetHeight = offsetHeight === Math.round(height) ? height : offsetHeight;
75-
76-
const sizeInfo = {
77-
...size,
78-
offsetWidth: mergedOffsetWidth,
79-
offsetHeight: mergedOffsetHeight,
80-
};
81-
82-
// Let collection know what happened
83-
onCollectionResize?.(sizeInfo, target, data);
84-
85-
if (onResize) {
86-
// defer the callback but not defer to next frame
87-
Promise.resolve().then(() => {
88-
onResize(sizeInfo, target);
89-
});
90-
}
91-
}
92-
}, []);
93-
94-
// Dynamic observe
95-
React.useEffect(() => {
96-
const currentElement: HTMLElement = getDomElement();
97-
98-
if (currentElement && !disabled) {
99-
observe(currentElement, onInternalResize);
100-
}
101-
102-
return () => unobserve(currentElement, onInternalResize);
103-
}, [elementRef.current, disabled]);
36+
useResizeObserver(!disabled, getDomElement, onResize, (sizeInfo, target) => {
37+
onCollectionResize?.(sizeInfo, target, data);
38+
});
10439

10540
// ============================ Render ============================
106-
return (
107-
canRef
108-
? React.cloneElement(mergedChildren as any, {
109-
ref: mergedRef,
110-
})
111-
: mergedChildren
112-
);
41+
return canRef
42+
? React.cloneElement(mergedChildren as any, {
43+
ref: mergedRef,
44+
})
45+
: mergedChildren;
11346
}
11447

11548
const RefSingleObserver = React.forwardRef(SingleObserver);

src/useResizeObserver.ts

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,79 @@
1-
import type { OnResize } from '.';
1+
import * as React from 'react';
2+
import type { OnResize, SizeInfo } from '.';
3+
import { observe, unobserve } from './utils/observerUtil';
4+
import { useEvent } from '@rc-component/util';
25

3-
// TODO: Ref observerUtil.ts, realize this.
46
export default function useResizeObserver(
57
enabled: boolean,
68
getTarget: () => HTMLElement,
7-
onResize: OnResize,
8-
) {}
9+
onDelayResize?: OnResize,
10+
onSyncResize?: OnResize,
11+
) {
12+
// ============================= Size =============================
13+
const sizeRef = React.useRef<SizeInfo>({
14+
width: -1,
15+
height: -1,
16+
offsetWidth: -1,
17+
offsetHeight: -1,
18+
});
19+
20+
// =========================== Observe ============================
21+
22+
// Handler
23+
const onInternalResize = useEvent((target: HTMLElement) => {
24+
const { width, height } = target.getBoundingClientRect();
25+
const { offsetWidth, offsetHeight } = target;
26+
27+
/**
28+
* Resize observer trigger when content size changed.
29+
* In most case we just care about element size,
30+
* let's use `boundary` instead of `contentRect` here to avoid shaking.
31+
*/
32+
const fixedWidth = Math.floor(width);
33+
const fixedHeight = Math.floor(height);
34+
35+
if (
36+
sizeRef.current.width !== fixedWidth ||
37+
sizeRef.current.height !== fixedHeight ||
38+
sizeRef.current.offsetWidth !== offsetWidth ||
39+
sizeRef.current.offsetHeight !== offsetHeight
40+
) {
41+
const size = { width: fixedWidth, height: fixedHeight, offsetWidth, offsetHeight };
42+
sizeRef.current = size;
43+
44+
// IE is strange, right?
45+
const mergedOffsetWidth = offsetWidth === Math.round(width) ? width : offsetWidth;
46+
const mergedOffsetHeight = offsetHeight === Math.round(height) ? height : offsetHeight;
47+
48+
const sizeInfo = {
49+
...size,
50+
offsetWidth: mergedOffsetWidth,
51+
offsetHeight: mergedOffsetHeight,
52+
};
53+
54+
// Call the callback immediately, let the caller decide whether to defer
55+
// onResize(sizeInfo, target);
56+
onSyncResize?.(sizeInfo, target);
57+
58+
// defer the callback but not defer to next frame
59+
Promise.resolve().then(() => {
60+
onDelayResize?.(sizeInfo, target);
61+
});
62+
}
63+
});
64+
65+
// Dynamic observe
66+
React.useEffect(() => {
67+
const target = getTarget();
68+
69+
if (target && enabled) {
70+
observe(target, onInternalResize);
71+
}
72+
73+
return () => {
74+
if (target) {
75+
unobserve(target, onInternalResize);
76+
}
77+
};
78+
}, [enabled, getTarget]);
79+
}

0 commit comments

Comments
 (0)