RN: Remove Native Prop Validation
Summary: As we migrate over to static typing solutions for props, we cannot rely on always having `propTypes` available at runtime. This gets us started on that journey by removing the native prop validation that happens when we require native components. bypass-lint Reviewed By: TheSavior Differential Revision: D7976854 fbshipit-source-id: f3ab579a7f0f8cfb716b0eb7fd4625f8168f3d96
This commit is contained in:
parent
6c910549d8
commit
8dc3ba0444
|
@ -11,7 +11,6 @@
|
|||
'use strict';
|
||||
|
||||
const Platform = require('Platform');
|
||||
const ProgressBarAndroid = require('ProgressBarAndroid');
|
||||
const React = require('React');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const View = require('View');
|
||||
|
@ -21,7 +20,10 @@ const requireNativeComponent = require('requireNativeComponent');
|
|||
import type {NativeComponent} from 'ReactNative';
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
let RCTActivityIndicator;
|
||||
const RCTActivityIndicator =
|
||||
Platform.OS === 'android'
|
||||
? require('ProgressBarAndroid')
|
||||
: requireNativeComponent('RCTActivityIndicatorView');
|
||||
|
||||
const GRAY = '#999999';
|
||||
|
||||
|
@ -98,11 +100,7 @@ const ActivityIndicator = (
|
|||
|
||||
return (
|
||||
<View onLayout={onLayout} style={[styles.container, style]}>
|
||||
{Platform.OS === 'ios' ? (
|
||||
<RCTActivityIndicator {...nativeProps} />
|
||||
) : (
|
||||
<ProgressBarAndroid {...nativeProps} />
|
||||
)}
|
||||
<RCTActivityIndicator {...nativeProps} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
@ -120,14 +118,6 @@ ActivityIndicatorWithRef.defaultProps = {
|
|||
};
|
||||
ActivityIndicatorWithRef.displayName = 'ActivityIndicator';
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
RCTActivityIndicator = requireNativeComponent(
|
||||
'RCTActivityIndicatorView',
|
||||
null,
|
||||
{nativeOnly: {activityIndicatorViewStyle: true}},
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
alignItems: 'center',
|
||||
|
|
|
@ -22,6 +22,8 @@ const requireNativeComponent = require('requireNativeComponent');
|
|||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
const RCTDatePickerIOS = requireNativeComponent('RCTDatePicker');
|
||||
|
||||
type Event = Object;
|
||||
|
||||
type Props = $ReadOnly<{|
|
||||
|
@ -177,6 +179,4 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
const RCTDatePickerIOS = requireNativeComponent('RCTDatePicker');
|
||||
|
||||
module.exports = DatePickerIOS;
|
||||
|
|
|
@ -17,6 +17,8 @@ const requireNativeComponent = require('requireNativeComponent');
|
|||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
const RCTMaskedView = requireNativeComponent('RCTMaskedView');
|
||||
|
||||
type Props = {
|
||||
...ViewProps,
|
||||
|
||||
|
@ -97,12 +99,4 @@ class MaskedViewIOS extends React.Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
const RCTMaskedView = requireNativeComponent('RCTMaskedView', {
|
||||
name: 'RCTMaskedView',
|
||||
displayName: 'RCTMaskedView',
|
||||
propTypes: {
|
||||
...ViewPropTypes,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = MaskedViewIOS;
|
||||
|
|
|
@ -25,6 +25,8 @@ import type {ImageSource} from 'ImageSource';
|
|||
import type {ColorValue} from 'StyleSheetTypes';
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
const RCTProgressView = requireNativeComponent('RCTProgressView');
|
||||
|
||||
type Props = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
progressViewStyle?: ?('default' | 'bar'),
|
||||
|
@ -91,11 +93,6 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
const RCTProgressView = requireNativeComponent(
|
||||
'RCTProgressView',
|
||||
ProgressViewIOS,
|
||||
);
|
||||
|
||||
module.exports = ((ProgressViewIOS: any): Class<
|
||||
ReactNative.NativeComponent<Props>,
|
||||
>);
|
||||
|
|
|
@ -14,6 +14,8 @@ const requireNativeComponent = require('requireNativeComponent');
|
|||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
const RCTSafeAreaView = requireNativeComponent('RCTSafeAreaView');
|
||||
|
||||
type Props = ViewProps & {
|
||||
children: any,
|
||||
};
|
||||
|
@ -34,12 +36,4 @@ class SafeAreaView extends React.Component<Props> {
|
|||
}
|
||||
}
|
||||
|
||||
const RCTSafeAreaView = requireNativeComponent('RCTSafeAreaView', {
|
||||
name: 'RCTSafeAreaView',
|
||||
displayName: 'RCTSafeAreaView',
|
||||
propTypes: {
|
||||
...ViewPropTypes,
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = SafeAreaView;
|
||||
|
|
|
@ -45,6 +45,28 @@ import type {PointProp} from 'PointPropType';
|
|||
|
||||
import type {ColorValue} from 'StyleSheetTypes';
|
||||
|
||||
let AndroidScrollView;
|
||||
let AndroidHorizontalScrollContentView;
|
||||
let AndroidHorizontalScrollView;
|
||||
let RCTScrollView;
|
||||
let RCTScrollContentView;
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
AndroidScrollView = requireNativeComponent('RCTScrollView');
|
||||
AndroidHorizontalScrollView = requireNativeComponent(
|
||||
'AndroidHorizontalScrollView',
|
||||
);
|
||||
AndroidHorizontalScrollContentView = requireNativeComponent(
|
||||
'AndroidHorizontalScrollContentView',
|
||||
);
|
||||
} else if (Platform.OS === 'ios') {
|
||||
RCTScrollView = requireNativeComponent('RCTScrollView');
|
||||
RCTScrollContentView = requireNativeComponent('RCTScrollContentView');
|
||||
} else {
|
||||
RCTScrollView = requireNativeComponent('RCTScrollView');
|
||||
RCTScrollContentView = requireNativeComponent('RCTScrollContentView');
|
||||
}
|
||||
|
||||
type TouchableProps = $ReadOnly<{|
|
||||
onTouchStart?: (event: PressEvent) => void,
|
||||
onTouchMove?: (event: PressEvent) => void,
|
||||
|
@ -1074,56 +1096,4 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
let nativeOnlyProps,
|
||||
AndroidScrollView,
|
||||
AndroidHorizontalScrollContentView,
|
||||
AndroidHorizontalScrollView,
|
||||
RCTScrollView,
|
||||
RCTScrollContentView;
|
||||
if (Platform.OS === 'android') {
|
||||
nativeOnlyProps = {
|
||||
nativeOnly: {
|
||||
sendMomentumEvents: true,
|
||||
},
|
||||
};
|
||||
AndroidScrollView = requireNativeComponent(
|
||||
'RCTScrollView',
|
||||
(ScrollView: React.ComponentType<any>),
|
||||
nativeOnlyProps,
|
||||
);
|
||||
AndroidHorizontalScrollView = requireNativeComponent(
|
||||
'AndroidHorizontalScrollView',
|
||||
(ScrollView: React.ComponentType<any>),
|
||||
nativeOnlyProps,
|
||||
);
|
||||
AndroidHorizontalScrollContentView = requireNativeComponent(
|
||||
'AndroidHorizontalScrollContentView',
|
||||
);
|
||||
} else if (Platform.OS === 'ios') {
|
||||
nativeOnlyProps = {
|
||||
nativeOnly: {
|
||||
onMomentumScrollBegin: true,
|
||||
onMomentumScrollEnd: true,
|
||||
onScrollBeginDrag: true,
|
||||
onScrollEndDrag: true,
|
||||
},
|
||||
};
|
||||
RCTScrollView = requireNativeComponent(
|
||||
'RCTScrollView',
|
||||
(ScrollView: React.ComponentType<any>),
|
||||
nativeOnlyProps,
|
||||
);
|
||||
RCTScrollContentView = requireNativeComponent('RCTScrollContentView', View);
|
||||
} else {
|
||||
nativeOnlyProps = {
|
||||
nativeOnly: {},
|
||||
};
|
||||
RCTScrollView = requireNativeComponent(
|
||||
'RCTScrollView',
|
||||
null,
|
||||
nativeOnlyProps,
|
||||
);
|
||||
RCTScrollContentView = requireNativeComponent('RCTScrollContentView', View);
|
||||
}
|
||||
|
||||
module.exports = TypedScrollView;
|
||||
|
|
|
@ -22,6 +22,8 @@ const requireNativeComponent = require('requireNativeComponent');
|
|||
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
const RCTSegmentedControl = requireNativeComponent('RCTSegmentedControl');
|
||||
|
||||
type DefaultProps = {
|
||||
values: $ReadOnlyArray<string>,
|
||||
enabled: boolean,
|
||||
|
@ -139,11 +141,6 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
const RCTSegmentedControl = requireNativeComponent(
|
||||
'RCTSegmentedControl',
|
||||
SegmentedControlIOS,
|
||||
);
|
||||
|
||||
module.exports = ((SegmentedControlIOS: any): Class<
|
||||
ReactNative.NativeComponent<Props>,
|
||||
>);
|
||||
|
|
|
@ -29,6 +29,8 @@ import type {ViewStyleProp} from 'StyleSheet';
|
|||
import type {ColorValue} from 'StyleSheetTypes';
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
const RCTSlider = requireNativeComponent('RCTSlider');
|
||||
|
||||
type Event = Object;
|
||||
|
||||
type IOSProps = $ReadOnly<{|
|
||||
|
@ -306,14 +308,4 @@ if (Platform.OS === 'ios') {
|
|||
});
|
||||
}
|
||||
|
||||
let options = {};
|
||||
if (Platform.OS === 'android') {
|
||||
options = {
|
||||
nativeOnly: {
|
||||
enabled: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
const RCTSlider = requireNativeComponent('RCTSlider', Slider, options);
|
||||
|
||||
module.exports = ((Slider: any): Class<ReactNative.NativeComponent<Props>>);
|
||||
|
|
|
@ -25,6 +25,11 @@ const requireNativeComponent = require('requireNativeComponent');
|
|||
import type {ColorValue} from 'StyleSheetTypes';
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
const RCTSwitch =
|
||||
Platform.OS === 'android'
|
||||
? requireNativeComponent('AndroidSwitch')
|
||||
: requireNativeComponent('RCTSwitch');
|
||||
|
||||
type DefaultProps = $ReadOnly<{|
|
||||
value: boolean,
|
||||
disabled: boolean,
|
||||
|
@ -40,6 +45,7 @@ type Props = $ReadOnly<{|
|
|||
onTintColor?: ?ColorValue,
|
||||
thumbTintColor?: ?ColorValue,
|
||||
|}>;
|
||||
|
||||
/**
|
||||
* Renders a boolean input.
|
||||
*
|
||||
|
@ -158,21 +164,4 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
var RCTSwitch = requireNativeComponent('AndroidSwitch', Switch, {
|
||||
nativeOnly: {
|
||||
onChange: true,
|
||||
on: true,
|
||||
enabled: true,
|
||||
trackTintColor: true,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
var RCTSwitch = requireNativeComponent('RCTSwitch', Switch, {
|
||||
nativeOnly: {
|
||||
onChange: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = ((Switch: any): Class<ReactNative.NativeComponent<Props>>);
|
||||
|
|
|
@ -22,6 +22,8 @@ const requireNativeComponent = require('requireNativeComponent');
|
|||
import type {DangerouslyImpreciseStyleProp} from 'StyleSheet';
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
|
||||
const RCTTabBar = requireNativeComponent('RCTTabBar');
|
||||
|
||||
type Props = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
style?: DangerouslyImpreciseStyleProp,
|
||||
|
@ -102,6 +104,4 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
const RCTTabBar = requireNativeComponent('RCTTabBar', TabBarIOS);
|
||||
|
||||
module.exports = TabBarIOS;
|
||||
|
|
|
@ -40,24 +40,22 @@ let AndroidTextInput;
|
|||
let RCTMultilineTextInputView;
|
||||
let RCTSinglelineTextInputView;
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
AndroidTextInput = requireNativeComponent('AndroidTextInput');
|
||||
} else if (Platform.OS === 'ios') {
|
||||
RCTMultilineTextInputView = requireNativeComponent(
|
||||
'RCTMultilineTextInputView',
|
||||
);
|
||||
RCTSinglelineTextInputView = requireNativeComponent(
|
||||
'RCTSinglelineTextInputView',
|
||||
);
|
||||
}
|
||||
|
||||
const onlyMultiline = {
|
||||
onTextInput: true,
|
||||
children: true,
|
||||
};
|
||||
|
||||
if (Platform.OS === 'android') {
|
||||
AndroidTextInput = requireNativeComponent('AndroidTextInput', null);
|
||||
} else if (Platform.OS === 'ios') {
|
||||
RCTMultilineTextInputView = requireNativeComponent(
|
||||
'RCTMultilineTextInputView',
|
||||
null,
|
||||
);
|
||||
RCTSinglelineTextInputView = requireNativeComponent(
|
||||
'RCTSinglelineTextInputView',
|
||||
null,
|
||||
);
|
||||
}
|
||||
|
||||
type Event = Object;
|
||||
type Selection = {
|
||||
start: number,
|
||||
|
|
|
@ -10,11 +10,8 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const Platform = require('Platform');
|
||||
const React = require('React');
|
||||
const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
|
||||
const TextAncestor = require('TextAncestor');
|
||||
const ViewPropTypes = require('ViewPropTypes');
|
||||
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
const requireNativeComponent = require('requireNativeComponent');
|
||||
|
@ -31,31 +28,7 @@ export type Props = ViewProps;
|
|||
*
|
||||
* @see http://facebook.github.io/react-native/docs/view.html
|
||||
*/
|
||||
const RCTView = requireNativeComponent(
|
||||
'RCTView',
|
||||
{
|
||||
propTypes: ViewPropTypes,
|
||||
},
|
||||
{
|
||||
nativeOnly: {
|
||||
nativeBackgroundAndroid: true,
|
||||
nativeForegroundAndroid: true,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (__DEV__) {
|
||||
const UIManager = require('UIManager');
|
||||
const viewConfig =
|
||||
(UIManager.viewConfigs && UIManager.viewConfigs.RCTView) || {};
|
||||
for (const prop in viewConfig.nativeProps) {
|
||||
if (!ViewPropTypes[prop] && !ReactNativeStyleAttributes[prop]) {
|
||||
throw new Error(
|
||||
'View is missing propType for native prop `' + prop + '`',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
const RCTView = requireNativeComponent('RCTView');
|
||||
|
||||
let ViewToExport = RCTView;
|
||||
if (__DEV__) {
|
||||
|
|
|
@ -23,6 +23,8 @@ const resolveAssetSource = require('resolveAssetSource');
|
|||
|
||||
const ImageViewManager = NativeModules.ImageViewManager;
|
||||
|
||||
const RCTImageView = requireNativeComponent('RCTImageView');
|
||||
|
||||
/**
|
||||
* A React component for displaying different types of images,
|
||||
* including network images, static resources, temporary local images, and
|
||||
|
@ -139,6 +141,4 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
const RCTImageView = requireNativeComponent('RCTImageView', Image);
|
||||
|
||||
module.exports = Image;
|
||||
|
|
|
@ -22,7 +22,9 @@ const View = require('View');
|
|||
|
||||
const deprecatedPropType = require('deprecatedPropType');
|
||||
const requireNativeComponent = require('requireNativeComponent');
|
||||
const RCTModalHostView = requireNativeComponent('RCTModalHostView', null);
|
||||
|
||||
const RCTModalHostView = requireNativeComponent('RCTModalHostView');
|
||||
|
||||
const ModalEventEmitter =
|
||||
Platform.OS === 'ios' && NativeModules.ModalManager
|
||||
? new NativeEventEmitter(NativeModules.ModalManager)
|
||||
|
|
|
@ -21,6 +21,13 @@ const ViewPropTypes = require('ViewPropTypes');
|
|||
|
||||
const requireNativeComponent = require('requireNativeComponent');
|
||||
|
||||
// Verify that RCTSnapshot is part of the UIManager since it is only loaded
|
||||
// if you have linked against RCTTest like in tests, otherwise we will have
|
||||
// a warning printed out
|
||||
const RCTSnapshot = UIManager.RCTSnapshot
|
||||
? requireNativeComponent('RCTSnapshot')
|
||||
: View;
|
||||
|
||||
class SnapshotViewIOS extends React.Component<{
|
||||
onSnapshotReady?: Function,
|
||||
testIdentifier?: string,
|
||||
|
@ -59,11 +66,4 @@ const style = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
// Verify that RCTSnapshot is part of the UIManager since it is only loaded
|
||||
// if you have linked against RCTTest like in tests, otherwise we will have
|
||||
// a warning printed out
|
||||
const RCTSnapshot = UIManager.RCTSnapshot
|
||||
? requireNativeComponent('RCTSnapshot', SnapshotViewIOS)
|
||||
: View;
|
||||
|
||||
module.exports = SnapshotViewIOS;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const Platform = require('Platform');
|
||||
const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
|
||||
const UIManager = require('UIManager');
|
||||
|
||||
|
@ -21,51 +20,25 @@ const pointsDiffer = require('pointsDiffer');
|
|||
const processColor = require('processColor');
|
||||
const resolveAssetSource = require('resolveAssetSource');
|
||||
const sizesDiffer = require('sizesDiffer');
|
||||
const verifyPropTypes = require('verifyPropTypes');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
const warning = require('fbjs/lib/warning');
|
||||
|
||||
type ComponentInterface =
|
||||
| React$ComponentType<any>
|
||||
| $ReadOnly<{
|
||||
propTypes?: $ReadOnly<{
|
||||
[propName: string]: mixed,
|
||||
}>,
|
||||
}>;
|
||||
|
||||
type ExtraOptions = $ReadOnly<{|
|
||||
nativeOnly?: $ReadOnly<{
|
||||
[propName: string]: boolean,
|
||||
}>,
|
||||
|}>;
|
||||
|
||||
/**
|
||||
* Used to create React components that directly wrap native component
|
||||
* implementations. Config information is extracted from data exported from the
|
||||
* UIManager module. You should also wrap the native component in a
|
||||
* hand-written component with full propTypes definitions and other
|
||||
* documentation - pass the hand-written component in as `componentInterface` to
|
||||
* verify all the native props are documented via `propTypes`.
|
||||
* Creates values that can be used like React components which represent native
|
||||
* view managers. You should create JavaScript modules that wrap these values so
|
||||
* that the results are memoized. Example:
|
||||
*
|
||||
* If some native props shouldn't be exposed in the wrapper interface, you can
|
||||
* pass null for `componentInterface` and call `verifyPropTypes` directly
|
||||
* with `nativePropsToIgnore`;
|
||||
* const View = requireNativeComponent('RCTView');
|
||||
*
|
||||
* Common types are lined up with the appropriate prop differs with
|
||||
* `TypeToDifferMap`. Non-scalar types not in the map default to `deepDiffer`.
|
||||
*/
|
||||
const requireNativeComponent = (
|
||||
viewName: string,
|
||||
componentInterface?: ?ComponentInterface,
|
||||
extraConfig?: ?ExtraOptions,
|
||||
): string =>
|
||||
createReactNativeComponentClass(viewName, () => {
|
||||
const viewConfig = UIManager[viewName];
|
||||
const requireNativeComponent = (uiViewClassName: string): string =>
|
||||
createReactNativeComponentClass(uiViewClassName, () => {
|
||||
const viewConfig = UIManager[uiViewClassName];
|
||||
|
||||
invariant(
|
||||
viewConfig != null && viewConfig.NativeProps != null,
|
||||
'requireNativeComponent: "%s" was not found in the UIManager.',
|
||||
viewName,
|
||||
uiViewClassName,
|
||||
);
|
||||
|
||||
// TODO: This seems like a whole lot of runtime initialization for every
|
||||
|
@ -94,14 +67,14 @@ const requireNativeComponent = (
|
|||
}
|
||||
}
|
||||
|
||||
const viewAttributes = {};
|
||||
const validAttributes = {};
|
||||
|
||||
for (const key in nativeProps) {
|
||||
const typeName = nativeProps[key];
|
||||
const diff = getDifferForType(typeName);
|
||||
const process = getProcessorForType(typeName);
|
||||
|
||||
viewAttributes[key] =
|
||||
validAttributes[key] =
|
||||
diff == null && process == null ? true : {diff, process};
|
||||
}
|
||||
|
||||
|
@ -109,24 +82,15 @@ const requireNativeComponent = (
|
|||
// props. This makes it so we allow style properties in the `style` prop.
|
||||
// TODO: Move style properties into a `style` prop and disallow them as
|
||||
// top-level props on the native side.
|
||||
viewAttributes.style = ReactNativeStyleAttributes;
|
||||
validAttributes.style = ReactNativeStyleAttributes;
|
||||
|
||||
Object.assign(viewConfig, {
|
||||
uiViewClassName: viewName,
|
||||
validAttributes: viewAttributes,
|
||||
propTypes:
|
||||
componentInterface == null ? null : componentInterface.propTypes,
|
||||
uiViewClassName,
|
||||
validAttributes,
|
||||
bubblingEventTypes,
|
||||
directEventTypes,
|
||||
});
|
||||
|
||||
if (__DEV__) {
|
||||
verifyPropTypes(
|
||||
viewConfig,
|
||||
extraConfig == null ? null : extraConfig.nativeOnly,
|
||||
);
|
||||
}
|
||||
|
||||
if (!hasAttachedDefaultEventTypes) {
|
||||
attachDefaultEventTypes(viewConfig);
|
||||
hasAttachedDefaultEventTypes = true;
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
|
||||
|
||||
function verifyPropTypes(
|
||||
viewConfig: $ReadOnly<{
|
||||
NativeProps: $ReadOnly<{
|
||||
[propName: string]: mixed,
|
||||
}>,
|
||||
propTypes: ?$ReadOnly<{
|
||||
[propName: string]: mixed,
|
||||
}>,
|
||||
uiViewClassName: string,
|
||||
}>,
|
||||
nativePropsToIgnore: ?$ReadOnly<{
|
||||
[propName: string]: boolean,
|
||||
}>,
|
||||
) {
|
||||
const {NativeProps, propTypes, uiViewClassName} = viewConfig;
|
||||
|
||||
if (propTypes == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const propName in NativeProps) {
|
||||
if (
|
||||
propTypes[propName] ||
|
||||
ReactNativeStyleAttributes[propName] ||
|
||||
(nativePropsToIgnore && nativePropsToIgnore[propName])
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const prettyName = `${uiViewClassName}.${propName}`;
|
||||
const nativeType = String(NativeProps[propName]);
|
||||
const suggestion =
|
||||
'\n\nIf you have not changed this prop yourself, this usually means ' +
|
||||
'that the versions of your native and JavaScript code are out of sync. ' +
|
||||
'Updating both should make this error go away.';
|
||||
|
||||
if (propTypes.hasOwnProperty(propName)) {
|
||||
console.error(
|
||||
`Invalid propType to configure \`${prettyName}\` (${nativeType}).` +
|
||||
suggestion,
|
||||
);
|
||||
} else {
|
||||
console.error(
|
||||
`Missing a propType to configure \`${prettyName}\` (${nativeType}).` +
|
||||
suggestion,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = verifyPropTypes;
|
Loading…
Reference in New Issue