diff --git a/Libraries/LayoutAnimation/LayoutAnimation.js b/Libraries/LayoutAnimation/LayoutAnimation.js index a8c20e3960c776..e4489d0543bf60 100644 --- a/Libraries/LayoutAnimation/LayoutAnimation.js +++ b/Libraries/LayoutAnimation/LayoutAnimation.js @@ -17,6 +17,7 @@ import type { LayoutAnimationType, } from '../Renderer/shims/ReactNativeTypes'; +import {getFabricUIManager} from '../ReactNative/FabricUIManager'; import ReactNativeFeatureFlags from '../ReactNative/ReactNativeFeatureFlags'; import Platform from '../Utilities/Platform'; @@ -77,7 +78,7 @@ function configureNext( // In Fabric, LayoutAnimations are unconditionally enabled for Android, and // conditionally enabled on iOS (pending fully shipping; this is a temporary state). - const FabricUIManager: FabricUIManagerSpec = global?.nativeFabricUIManager; + const FabricUIManager = getFabricUIManager(); if (FabricUIManager?.configureNextLayoutAnimation) { global?.nativeFabricUIManager?.configureNextLayoutAnimation( config, diff --git a/Libraries/ReactNative/FabricUIManager.js b/Libraries/ReactNative/FabricUIManager.js index 71f7f8fe4dc18e..4adf2cc2f63d09 100644 --- a/Libraries/ReactNative/FabricUIManager.js +++ b/Libraries/ReactNative/FabricUIManager.js @@ -59,6 +59,9 @@ export type Spec = {| +findShadowNodeByTag_DEPRECATED: (reactTag: number) => ?Node, |}; -const FabricUIManager: ?Spec = global.nativeFabricUIManager; - -module.exports = FabricUIManager; +// This is exposed as a getter because apps using the legacy renderer AND +// Fabric can define the binding lazily. If we evaluated the global and cached +// it in the module we might be caching an `undefined` value before it is set. +export function getFabricUIManager(): ?Spec { + return global.nativeFabricUIManager; +} diff --git a/Libraries/ReactNative/UIManager.js b/Libraries/ReactNative/UIManager.js index ac28590f23deef..71c124f312065b 100644 --- a/Libraries/ReactNative/UIManager.js +++ b/Libraries/ReactNative/UIManager.js @@ -12,6 +12,9 @@ import type {RootTag} from '../Types/RootTagTypes'; import type {Spec as FabricUIManagerSpec} from './FabricUIManager'; import type {Spec} from './NativeUIManager'; +import {getFabricUIManager} from './FabricUIManager'; +import nullthrows from 'nullthrows'; + export interface UIManagerJSInterface extends Spec { +getViewManagerConfig: (viewManagerName: string) => Object; +hasViewManagerConfig: (viewManagerName: string) => boolean; @@ -57,8 +60,7 @@ const UIManager = { ) => void, ): void { if (isFabricReactTag(reactTag)) { - const FabricUIManager: FabricUIManagerSpec = - global?.nativeFabricUIManager; + const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); if (shadowNode) { @@ -84,8 +86,7 @@ const UIManager = { ) => void, ): void { if (isFabricReactTag(reactTag)) { - const FabricUIManager: FabricUIManagerSpec = - global?.nativeFabricUIManager; + const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); if (shadowNode) { @@ -113,8 +114,7 @@ const UIManager = { ) => void, ): void { if (isFabricReactTag(reactTag)) { - const FabricUIManager: FabricUIManagerSpec = - global?.nativeFabricUIManager; + const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); const ancestorShadowNode = @@ -155,8 +155,7 @@ const UIManager = { console.warn( 'RCTUIManager.measureLayoutRelativeToParent method is deprecated and it will not be implemented in newer versions of RN (Fabric) - T47686450', ); - const FabricUIManager: FabricUIManagerSpec = - global?.nativeFabricUIManager; + const FabricUIManager = nullthrows(getFabricUIManager()); const shadowNode = FabricUIManager.findShadowNodeByTag_DEPRECATED(reactTag); if (shadowNode) {