UNPKG

2.96 kBJavaScriptView Raw
1import React from 'react';
2import omit from 'lodash.omit';
3import pick from 'lodash.pick';
4import PropTypes from 'prop-types';
5import { requireNativeComponent, ViewPropTypes, UIManager, NativeModules } from 'react-native';
6
7// We'd like to make the transition from react-native's
8// requireNativeComponent to expo-core's requireNativeViewManager
9// as easy as possible, so an obvious requirement will be to be able
10// to just replace the requireNativeComponent with requireNativeViewManager
11// call. If that's so, we have to wrap a native component in two middleware
12// components - the bottom one, near the requireNativeComponent call has to
13// define a propType for proxiedProperties (so that doesn't complain),
14// and the "top" one has to accept all the properties, split them into
15// props passed to react-native's View (like style, testID, etc.)
16// and custom view properties. For that we use
17// {omit,pick}(props, Object.keys(ViewPropTypes))
18
19const ViewPropTypesKeys = Object.keys(ViewPropTypes);
20
21const getViewManagerAdapterNameForViewName = name => `ViewManagerAdapter_${name}`;
22
23const createNativeComponentClass = name => {
24 class NativeComponent extends React.Component {
25 static propTypes = { ...ViewPropTypes, proxiedProperties: PropTypes.object };
26 render() {
27 return <UnderlyingNativeComponent {...this.props} />;
28 }
29 }
30
31 const nativeComponentName = getViewManagerAdapterNameForViewName(name);
32
33 const UnderlyingNativeComponent = requireNativeComponent(nativeComponentName, NativeComponent, {
34 nativeOnly: Object.keys(UIManager[nativeComponentName].NativeProps).reduce(
35 (acc, key) => ({ ...acc, [key]: true }),
36 {}
37 ),
38 });
39
40 NativeComponent.displayName = name;
41 return NativeComponent;
42};
43
44export const requireNativeViewManager = (name, component) => {
45 if (!NativeModules.ExpoNativeModuleProxy.viewManagersNames.includes(name)) {
46 console.warn(
47 "It seems the native view manager which you're trying to require by name" +
48 "from NativeViewManagerAdapter isn't exported by expo-react-native-adapter." +
49 ' Things may not work properly. Exported view managers: [' +
50 NativeModules.ExpoNativeModuleProxy.viewManagersNames.join(', ') +
51 `], and you required "${name}".`
52 );
53 }
54
55 const NativeComponent = createNativeComponentClass(name);
56 const PropTypesKeys = [
57 'children',
58 ...ViewPropTypesKeys,
59 ...Object.keys(UIManager[getViewManagerAdapterNameForViewName(name)].NativeProps),
60 ...Object.keys(UIManager[getViewManagerAdapterNameForViewName(name)].directEventTypes),
61 ];
62 class NativeComponentWrapper extends React.Component {
63 render() {
64 const nativeProps = pick(this.props, PropTypesKeys);
65 const proxiedProps = omit(this.props, PropTypesKeys);
66 return <NativeComponent proxiedProperties={proxiedProps} {...nativeProps} />;
67 }
68 }
69 NativeComponentWrapper.displayName = `ViewWrapper<${name}>`;
70 return NativeComponentWrapper;
71};