react-native/Libraries/ReactNative/verifyPropTypes.js
Eli White dbdf43b428 propTypes are optional for native components
Summary:
We plan to migrate native components like View, Text, and Image to be typed with Flow instead of propTypes so that we can better enforce our usages.

This change makes it so that *if* propTypes are defined they must cover the native props. However, if they aren't specified, the validation doesn't occur.

Eventually, the prop validation should occur via codegen that generates an interface the native component must implement from the flow types defined in JS.

Reviewed By: yungsters

Differential Revision: D7203649

fbshipit-source-id: a8095aa46807ce03272e2962289e8f5705b422b9
2018-03-08 15:56:09 -08:00

87 lines
2.4 KiB
JavaScript

/**
* 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.
*
* @providesModule verifyPropTypes
* @flow
* @format
*/
'use strict';
var ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
export type ComponentInterface =
| React$ComponentType<any>
| {
name?: string,
displayName?: string,
propTypes?: Object,
};
function verifyPropTypes(
componentInterface: ComponentInterface,
viewConfig: Object,
nativePropsToIgnore?: ?Object,
) {
if (!viewConfig) {
return; // This happens for UnimplementedView.
}
var componentName =
componentInterface.displayName || componentInterface.name || 'unknown';
// ReactNative `View.propTypes` have been deprecated in favor of
// `ViewPropTypes`. In their place a temporary getter has been added with a
// deprecated warning message. Avoid triggering that warning here by using
// temporary workaround, __propTypesSecretDontUseThesePlease.
// TODO (bvaughn) Revert this particular change any time after April 1
var propTypes =
(componentInterface: any).__propTypesSecretDontUseThesePlease ||
componentInterface.propTypes;
if (!propTypes) {
return;
}
var nativeProps = viewConfig.NativeProps;
for (var prop in nativeProps) {
if (
!propTypes[prop] &&
!ReactNativeStyleAttributes[prop] &&
(!nativePropsToIgnore || !nativePropsToIgnore[prop])
) {
var message;
if (propTypes.hasOwnProperty(prop)) {
message =
'`' +
componentName +
'` has incorrectly defined propType for native prop `' +
viewConfig.uiViewClassName +
'.' +
prop +
'` of native type `' +
nativeProps[prop];
} else {
message =
'`' +
componentName +
'` has no propType for native prop `' +
viewConfig.uiViewClassName +
'.' +
prop +
'` of native type `' +
nativeProps[prop] +
'`';
}
message +=
"\nIf you haven't changed this prop yourself, this usually means that " +
'your versions of the native code and JavaScript code are out of sync. Updating both ' +
'should make this error go away.';
throw new Error(message);
}
}
}
module.exports = verifyPropTypes;