|
1 | 1 | import React, {
|
| 2 | + Ref, |
2 | 3 | useRef,
|
3 | 4 | useEffect,
|
4 | 5 | RefCallback,
|
@@ -32,6 +33,20 @@ const eventTypeMapping = {
|
32 | 33 | touchend: 'onTouchEnd'
|
33 | 34 | };
|
34 | 35 |
|
| 36 | +function useForkRef<T = any>( |
| 37 | + ...refs: Array<Ref<T> | undefined> |
| 38 | +): RefCallback<T> { |
| 39 | + return (node: T) => { |
| 40 | + refs.forEach((ref) => { |
| 41 | + if (typeof ref === 'function') { |
| 42 | + ref(node); |
| 43 | + } else if (ref != null && typeof ref === 'object') { |
| 44 | + (ref as MutableRefObject<T | null>).current = node; |
| 45 | + } |
| 46 | + }); |
| 47 | + }; |
| 48 | +} |
| 49 | + |
35 | 50 | const ClickAwayListener: FunctionComponent<Props> = ({
|
36 | 51 | children,
|
37 | 52 | onClickAway,
|
@@ -69,19 +84,9 @@ const ClickAwayListener: FunctionComponent<Props> = ({
|
69 | 84 | }
|
70 | 85 | };
|
71 | 86 |
|
72 |
| - const handleChildRef = (childRef: HTMLElement) => { |
73 |
| - node.current = childRef; |
74 |
| - |
75 |
| - let { ref } = children as typeof children & { |
76 |
| - ref: RefCallback<HTMLElement> | MutableRefObject<HTMLElement>; |
77 |
| - }; |
78 |
| - |
79 |
| - if (typeof ref === 'function') { |
80 |
| - ref(childRef); |
81 |
| - } else if (ref) { |
82 |
| - ref.current = childRef; |
83 |
| - } |
84 |
| - }; |
| 87 | + const combinedRef = useForkRef((ref) => { |
| 88 | + node.current = ref; |
| 89 | + }, (children as any).ref); |
85 | 90 |
|
86 | 91 | useEffect(() => {
|
87 | 92 | const nodeDocument = node.current?.ownerDocument ?? document;
|
@@ -117,7 +122,7 @@ const ClickAwayListener: FunctionComponent<Props> = ({
|
117 | 122 |
|
118 | 123 | return React.Children.only(
|
119 | 124 | cloneElement(children as ReactElement<any>, {
|
120 |
| - ref: handleChildRef, |
| 125 | + ref: combinedRef, |
121 | 126 | [mappedFocusEvent]: handleBubbledEvents(mappedFocusEvent),
|
122 | 127 | [mappedMouseEvent]: handleBubbledEvents(mappedMouseEvent),
|
123 | 128 | [mappedTouchEvent]: handleBubbledEvents(mappedTouchEvent)
|
|
0 commit comments