From c09ab5233976869d65a5419279ddef2b70467c0f Mon Sep 17 00:00:00 2001 From: Andrei Calazans Date: Tue, 13 Sep 2022 10:35:58 -0300 Subject: [PATCH] refactor: replace findNodeHandle for getRefNativeTag --- src/hooks/useScrollable.ts | 4 +-- src/hooks/useScrollableSetter.ts | 4 +-- src/utilities/getRefNativeTag.ts | 43 ++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 src/utilities/getRefNativeTag.ts diff --git a/src/hooks/useScrollable.ts b/src/hooks/useScrollable.ts index db7bb95a..39631757 100644 --- a/src/hooks/useScrollable.ts +++ b/src/hooks/useScrollable.ts @@ -1,6 +1,6 @@ import { useCallback, RefObject, useRef } from 'react'; -import { findNodeHandle } from 'react-native'; import { useSharedValue } from 'react-native-reanimated'; +import { getRefNativeTag } from '../utilities/getRefNativeTag'; import { SCROLLABLE_STATE, SCROLLABLE_TYPE } from '../constants'; import type { ScrollableRef, Scrollable } from '../types'; @@ -38,7 +38,7 @@ export const useScrollable = () => { // find node handle id let id; try { - id = findNodeHandle(ref.current); + id = getRefNativeTag(ref); } catch { return; } diff --git a/src/hooks/useScrollableSetter.ts b/src/hooks/useScrollableSetter.ts index 6797e0f3..ea7d3c24 100644 --- a/src/hooks/useScrollableSetter.ts +++ b/src/hooks/useScrollableSetter.ts @@ -1,7 +1,7 @@ import React, { useCallback, useEffect } from 'react'; -import { findNodeHandle } from 'react-native'; import Animated from 'react-native-reanimated'; import { useBottomSheetInternal } from './useBottomSheetInternal'; +import { getRefNativeTag } from '../utilities/getRefNativeTag'; import { SCROLLABLE_TYPE } from '../constants'; import type { Scrollable } from '../types'; @@ -31,7 +31,7 @@ export const useScrollableSetter = ( isContentHeightFixed.value = false; // set current scrollable ref - const id = findNodeHandle(ref.current); + const id = getRefNativeTag(ref); if (id) { setScrollableRef({ id: id, diff --git a/src/utilities/getRefNativeTag.ts b/src/utilities/getRefNativeTag.ts new file mode 100644 index 00000000..d4f3cc42 --- /dev/null +++ b/src/utilities/getRefNativeTag.ts @@ -0,0 +1,43 @@ +const isFunction = (ref: unknown): ref is Function => typeof ref === 'function'; + +const hasNativeTag = ( + ref: unknown +): ref is { current: { _nativeTag: number } } => + !!ref && + typeof ref === 'object' && + 'current' in (ref || {}) && + '_nativeTag' in ((ref as any)?.current || {}); + +/* + * getRefNativeTag is an internal utility used by createBottomSheetScrollableComponent + * to grab the native tag from the native host component. It only works when the ref + * is pointing to a native Host component. + * + * Internally in the bottom-sheet library ref can be a function that returns a native tag + * this seems to happen due to the usage of Reanimated's animated scroll components. + * + * This should be Fabric compatible as long as the ref is a native host component. + * */ +export function getRefNativeTag(ref: unknown) { + const refType = typeof ref; + let nativeTag: undefined | number; + if (isFunction(ref)) { + nativeTag = ref(); + } else if (hasNativeTag(ref)) { + nativeTag = ref.current._nativeTag; + } + + if (!nativeTag || typeof nativeTag !== 'number') { + throw new Error( + `Unexpected nativeTag: ${refType}; nativeTag=${nativeTag} + + createBottomSheetScrollableComponent's ScrollableComponent needs to return + a reference that contains a nativeTag to a Native HostComponent. + + ref=${ref} + ` + ); + } + + return nativeTag; +}