1import React from 'react'; 2import { findNodeHandle, NativeModules, requireNativeComponent } from 'react-native'; 3import { requireNativeModule } from './requireNativeModule'; 4// To make the transition from React Native's `requireNativeComponent` to Expo's 5// `requireNativeViewManager` as easy as possible, `requireNativeViewManager` is a drop-in 6// replacement for `requireNativeComponent`. 7// 8// For each view manager, we create a wrapper component that accepts all of the props available to 9// the author of the universal module. This wrapper component splits the props into two sets: props 10// passed to React Native's View (ex: style, testID) and custom view props, which are passed to the 11// adapter view component in a prop called `proxiedProperties`. 12/** 13 * A map that caches registered native components. 14 */ 15const nativeComponentsCache = new Map(); 16/** 17 * Requires a React Native component from cache if possible. This prevents 18 * "Tried to register two views with the same name" errors on fast refresh, but 19 * also when there are multiple versions of the same package with native component. 20 */ 21function requireCachedNativeComponent(viewName) { 22 const cachedNativeComponent = nativeComponentsCache.get(viewName); 23 if (!cachedNativeComponent) { 24 const nativeComponent = requireNativeComponent(viewName); 25 nativeComponentsCache.set(viewName, nativeComponent); 26 return nativeComponent; 27 } 28 return cachedNativeComponent; 29} 30/** 31 * A drop-in replacement for `requireNativeComponent`. 32 */ 33export function requireNativeViewManager(viewName) { 34 const { viewManagersMetadata } = NativeModules.NativeUnimoduleProxy; 35 const viewManagerConfig = viewManagersMetadata?.[viewName]; 36 if (__DEV__ && !viewManagerConfig) { 37 const exportedViewManagerNames = Object.keys(viewManagersMetadata).join(', '); 38 console.warn(`The native view manager required by name (${viewName}) from NativeViewManagerAdapter isn't exported by expo-modules-core. Views of this type may not render correctly. Exported view managers: [${exportedViewManagerNames}].`); 39 } 40 // Set up the React Native native component, which is an adapter to the universal module's view 41 // manager 42 const reactNativeViewName = `ViewManagerAdapter_${viewName}`; 43 const ReactNativeComponent = requireCachedNativeComponent(reactNativeViewName); 44 class NativeComponent extends React.PureComponent { 45 static displayName = viewName; 46 // This will be accessed from native when the prototype functions are called, 47 // in order to find the associated native view. 48 nativeTag = null; 49 componentDidMount() { 50 this.nativeTag = findNodeHandle(this); 51 } 52 render() { 53 return React.createElement(ReactNativeComponent, { ...this.props }); 54 } 55 } 56 try { 57 const nativeModule = requireNativeModule(viewName); 58 const nativeViewPrototype = nativeModule.ViewPrototype; 59 if (nativeViewPrototype) { 60 // Assign native view functions to the component prototype so they can be accessed from the ref. 61 Object.assign(NativeComponent.prototype, nativeViewPrototype); 62 } 63 } 64 catch { 65 // `requireNativeModule` may throw an error when the native module cannot be found. 66 // In some tests we don't mock the entire modules, but we do want to mock native views. For now, 67 // until we still have to support the legacy modules proxy and don't have better ways to mock, 68 // let's just gracefully skip assigning the prototype functions. 69 // See: https://github.com/expo/expo/blob/main/packages/expo-modules-core/src/__tests__/NativeViewManagerAdapter-test.native.tsx 70 } 71 return NativeComponent; 72} 73//# sourceMappingURL=NativeViewManagerAdapter.native.js.map