UNPKG

@elastic/eui

Version:

Elastic UI Component Library

62 lines (57 loc) 2.84 kB
/* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ import { useCallback, useEffect, useRef } from 'react'; /** * A shared custom hook that provides a pattern for observing DOM nodes * via browser observer APIs. Used by `EuiResizeObserver` and `EuiMutationObserver`. * * @param beginObserve - A callback that receives the target DOM element and should * create and return the observer instance (e.g., `ResizeObserver`). * @param componentName - Optional name used in error messages when no ref is * attached on mount, mirroring the guard previously in `EuiObserver`. */ export var useObserver = function useObserver(beginObserve) { var componentName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'useObserver'; var childNodeRef = useRef(null); var observerRef = useRef(null); // Store beginObserve in a ref so the ref callback doesn't cycle var beginObserveRef = useRef(beginObserve); beginObserveRef.current = beginObserve; // Store componentName in a ref so the mount-only effect can access the // latest value without needing it as a dependency. var componentNameRef = useRef(componentName); componentNameRef.current = componentName; // Guard: throw if the ref callback was never called (no element attached), // mirroring the check previously in EuiObserver.componentDidMount. // Also cleans up the observer on unmount. // Empty deps: run only on mount/unmount — componentName is only used for the // error message and changing it must not disconnect/re-connect the observer. useEffect(function () { if (childNodeRef.current == null) { throw new Error("".concat(componentNameRef.current, " did not receive a ref")); } return function () { var _observerRef$current; (_observerRef$current = observerRef.current) === null || _observerRef$current === void 0 || _observerRef$current.disconnect(); }; }, []); var updateChildNode = useCallback(function (ref) { if (childNodeRef.current === ref) return; // node hasn't changed // if there's an existing observer disconnect it if (observerRef.current != null) { observerRef.current.disconnect(); observerRef.current = null; } childNodeRef.current = ref; if (childNodeRef.current != null) { var _beginObserveRef$curr; observerRef.current = (_beginObserveRef$curr = beginObserveRef.current(childNodeRef.current)) !== null && _beginObserveRef$curr !== void 0 ? _beginObserveRef$curr : null; } }, []); return updateChildNode; };