import * as React from 'react'; import { setRef } from '../lib/utils'; class ExternalRef implements React.RefObject { #element: T | null = null; readonly #externRefs = new Set>(); constructor(externRefs: Array | undefined | false> = []) { externRefs.forEach((ref) => { if (ref) { this.#externRefs.add(ref); } }); } updateExternRefs(refs: Array | undefined | false>) { refs.forEach((ref) => { if (!ref || this.#externRefs.has(ref)) { return; } setRef(this.#element, ref); this.#externRefs.add(ref); }); } get current() { return this.#element; } set current(el) { this.#element = el; this.#externRefs.forEach((ref) => setRef(el, ref)); } /** * React проверяет наличие свойства current у объектов через hasOwnProperty * * https://github.com/facebook/react/blob/c3cdbec0a78d39b5ff7329384cb41c4573a38212/packages/react-reconciler/src/ReactFiberCommitWork.js#L1612 */ hasOwnProperty(v: PropertyKey): v is keyof ExternalRef { return v === 'current'; } } export function useExternRef( ...externRefs: Array | undefined | false> ): React.RefObject { const ref = React.useRef | null>(null); if (ref.current === null) { ref.current = new ExternalRef(externRefs); } else { ref.current.updateExternRefs(externRefs); } return ref.current; }