react-native-reanimated
Version:
More powerful alternative to Animated library for React Native.
101 lines (89 loc) • 3.44 kB
text/typescript
/* eslint-disable camelcase */
;
import type { InternalHostInstance } from '../commonTypes';
import type { IAnimatedComponentInternalBase } from '../createAnimatedComponent/commonTypes';
import type { HostInstance } from './types';
function findHostInstanceFastPath(maybeNativeRef: HostInstance | undefined) {
if (!maybeNativeRef) {
return undefined;
}
if (
maybeNativeRef.__internalInstanceHandle &&
maybeNativeRef.__nativeTag &&
// ReactFabricHostComponent (e.g. react-native-macos) exposes `_viewConfig`;
// ReactNativeElement uses `__viewConfig`.
(maybeNativeRef.__viewConfig || maybeNativeRef._viewConfig)
) {
return maybeNativeRef;
}
// That means it’s a ref to a non-native component, and it’s necessary
// to call `findHostInstance_DEPRECATED` on them.
return undefined;
}
type ScrollableRef = {
getNativeScrollRef?: () => HostInstance | null;
getScrollableNode?: () => HostInstance | number | null;
};
function findHostInstanceFromScrollableRef(
maybeScrollableRef: ScrollableRef | undefined
) {
if (!maybeScrollableRef) {
return undefined;
}
const nativeScrollRef = maybeScrollableRef.getNativeScrollRef?.();
if (nativeScrollRef) {
const hostInstance = findHostInstanceFastPath(nativeScrollRef);
if (hostInstance !== undefined) {
return hostInstance;
}
}
const scrollableNode = maybeScrollableRef.getScrollableNode?.();
if (!scrollableNode || typeof scrollableNode === 'number') {
return undefined;
}
return findHostInstanceFastPath(scrollableNode);
}
function resolveFindHostInstance_DEPRECATED() {
if (findHostInstance_DEPRECATED !== undefined) {
return;
}
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
const ReactFabric = require('react-native/Libraries/Renderer/shims/ReactFabric');
// Since RN 0.77 ReactFabric exports findHostInstance_DEPRECATED in default object so we're trying to
// access it first, then fallback on named export
findHostInstance_DEPRECATED =
ReactFabric?.default?.findHostInstance_DEPRECATED ??
ReactFabric?.findHostInstance_DEPRECATED;
} catch (_e) {
throw new Error(
'[Reanimated] Failed to resolve findHostInstance_DEPRECATED'
);
}
}
let findHostInstance_DEPRECATED: (ref: unknown) => HostInstance;
export function findHostInstance(
ref: IAnimatedComponentInternalBase | InternalHostInstance
): HostInstance {
const componentRef = (ref as IAnimatedComponentInternalBase)
._componentRef as HostInstance;
// Fast path for native refs
const hostInstance = findHostInstanceFastPath(componentRef);
if (hostInstance !== undefined) {
return hostInstance;
}
const scrollableHostInstance = findHostInstanceFromScrollableRef(
componentRef as ScrollableRef | undefined
);
if (scrollableHostInstance !== undefined) {
return scrollableHostInstance;
}
resolveFindHostInstance_DEPRECATED();
/*
The Fabric implementation of `findHostInstance_DEPRECATED` requires a React ref as an argument
rather than a native ref. Prefer the resolved component ref when available so components can
forward their ref to the host view that should be animated. Components that expose an animatable
ref via `getAnimatableRef` already have it resolved into `_componentRef`.
*/
return findHostInstance_DEPRECATED(componentRef ?? ref);
}