Mirror: React hooks for accessible, common web interactions. UI super powers without the UI.
1import { useRef, ForwardedRef } from 'react';
2import { Ref } from './types';
3
4type RefWithState<T extends HTMLElement> = Ref<T> & {
5 _forwarded?: ForwardedRef<T>;
6 _current?: T | null;
7};
8
9export function useForwardedRef<T extends HTMLElement>(
10 forwarded: ForwardedRef<T>
11): Ref<T> {
12 const ref: RefWithState<T> = useRef<T>(null);
13 if (ref._forwarded !== forwarded) {
14 ref._forwarded = forwarded;
15 Object.defineProperty(ref, 'current', {
16 enumerable: true,
17 configurable: true,
18 get() {
19 return this._current || null;
20 },
21 set(value: T | null) {
22 this._current = value;
23 if (typeof this._forwarded === 'function') {
24 this._forwarded(value);
25 } else if (forwarded) {
26 this._forwarded.current = value;
27 }
28 },
29 });
30 }
31
32 return ref;
33}