Skip to content

Commit c185fff

Browse files
committed
fix: address PR review comments on useObserver hook
- Update JSDoc to mention both EuiResizeObserver and EuiMutationObserver - Add optional componentName parameter to useObserver - Add mount-time guard (throws if no ref received), matching EuiObserver.componentDidMount behavior - Merge cleanup useEffect into the guard effect for clarity - Pass componentName from EuiResizeObserver and EuiMutationObserver callers
1 parent 195b013 commit c185fff

File tree

3 files changed

+14
-6
lines changed

3 files changed

+14
-6
lines changed

packages/eui/src/components/observer/mutation_observer/mutation_observer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export const EuiMutationObserver: React.FunctionComponent<
4444
[mutationCallback]
4545
);
4646

47-
const updateChildNode = useObserver(beginObserve);
47+
const updateChildNode = useObserver(beginObserve, 'EuiMutationObserver');
4848

4949
return children(updateChildNode) as React.ReactElement;
5050
};

packages/eui/src/components/observer/observer.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@ export interface Observer {
1515

1616
/**
1717
* A shared custom hook that provides a pattern for observing DOM nodes
18-
* via browser observer APIs. Used by `EuiResizeObserver`.
18+
* via browser observer APIs. Used by `EuiResizeObserver` and `EuiMutationObserver`.
1919
*
2020
* @param beginObserve - A callback that receives the target DOM element and should
2121
* create and return the observer instance (e.g., `ResizeObserver`).
22+
* @param componentName - Optional name used in error messages when no ref is
23+
* attached on mount, mirroring the guard previously in `EuiObserver`.
2224
*/
2325
export const useObserver = (
24-
beginObserve: (node: Element) => Observer | undefined
26+
beginObserve: (node: Element) => Observer | undefined,
27+
componentName: string = 'useObserver'
2528
) => {
2629
const childNodeRef = useRef<Element | null>(null);
2730
const observerRef = useRef<Observer | null>(null);
@@ -30,12 +33,17 @@ export const useObserver = (
3033
const beginObserveRef = useRef(beginObserve);
3134
beginObserveRef.current = beginObserve;
3235

33-
// Clean up observer on unmount
36+
// Guard: throw if the ref callback was never called (no element attached),
37+
// mirroring the check previously in EuiObserver.componentDidMount.
38+
// Also cleans up the observer on unmount.
3439
useEffect(() => {
40+
if (childNodeRef.current == null) {
41+
throw new Error(`${componentName} did not receive a ref`);
42+
}
3543
return () => {
3644
observerRef.current?.disconnect();
3745
};
38-
}, []);
46+
}, []); // eslint-disable-line react-hooks/exhaustive-deps
3947

4048
const updateChildNode = useCallback((ref: Element | null) => {
4149
if (childNodeRef.current === ref) return; // node hasn't changed

packages/eui/src/components/observer/resize_observer/resize_observer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const EuiResizeObserver: React.FunctionComponent<
5151
[resizeCallback]
5252
);
5353

54-
const updateChildNode = useObserver(beginObserve);
54+
const updateChildNode = useObserver(beginObserve, 'EuiResizeObserver');
5555

5656
return children(updateChildNode) as React.ReactElement;
5757
};

0 commit comments

Comments
 (0)