From 820673e7076b5906ba50e09e40fb9a32cf500c1b Mon Sep 17 00:00:00 2001 From: Tim Yung Date: Mon, 7 May 2018 16:45:19 -0700 Subject: [PATCH] RN: Simplify `verifyPropTypes` Reviewed By: sahrens Differential Revision: D7893675 fbshipit-source-id: 74d1eff57201a2af4a12c39c4335e28ff9f14090 --- Libraries/Components/View/ViewPropTypes.js | 2 +- .../ReactNative/requireNativeComponent.js | 19 ++-- Libraries/ReactNative/verifyPropTypes.js | 94 ++++++++----------- 3 files changed, 52 insertions(+), 63 deletions(-) diff --git a/Libraries/Components/View/ViewPropTypes.js b/Libraries/Components/View/ViewPropTypes.js index 40cd8121cd9958..332059ab0a222a 100644 --- a/Libraries/Components/View/ViewPropTypes.js +++ b/Libraries/Components/View/ViewPropTypes.js @@ -425,7 +425,7 @@ module.exports = { * See http://facebook.github.io/react-native/docs/view.html#needsoffscreenalphacompositing */ needsOffscreenAlphaCompositing: PropTypes.bool, - + /** * Any additional platform-specific view prop types, or prop type overrides. */ diff --git a/Libraries/ReactNative/requireNativeComponent.js b/Libraries/ReactNative/requireNativeComponent.js index fae553f27ce61f..c6f2a35d352ac8 100644 --- a/Libraries/ReactNative/requireNativeComponent.js +++ b/Libraries/ReactNative/requireNativeComponent.js @@ -25,7 +25,13 @@ const verifyPropTypes = require('verifyPropTypes'); const invariant = require('fbjs/lib/invariant'); const warning = require('fbjs/lib/warning'); -import type {ComponentInterface} from 'verifyPropTypes'; +type ComponentInterface = + | React$ComponentType + | $ReadOnly<{ + propTypes?: $ReadOnly<{ + [propName: string]: mixed, + }>, + }>; type ExtraOptions = $ReadOnly<{| nativeOnly?: $ReadOnly<{ @@ -115,13 +121,10 @@ const requireNativeComponent = ( }); if (__DEV__) { - if (componentInterface != null) { - verifyPropTypes( - componentInterface, - viewConfig, - extraConfig == null ? null : extraConfig.nativeOnly, - ); - } + verifyPropTypes( + viewConfig, + extraConfig == null ? null : extraConfig.nativeOnly, + ); } if (!hasAttachedDefaultEventTypes) { diff --git a/Libraries/ReactNative/verifyPropTypes.js b/Libraries/ReactNative/verifyPropTypes.js index c88f9c1c802904..6193b1ac1c03c8 100644 --- a/Libraries/ReactNative/verifyPropTypes.js +++ b/Libraries/ReactNative/verifyPropTypes.js @@ -4,73 +4,59 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow * @format + * @flow */ -'use strict'; -var ReactNativeStyleAttributes = require('ReactNativeStyleAttributes'); +'use strict'; -export type ComponentInterface = - | React$ComponentType - | { - name?: string, - displayName?: string, - propTypes?: Object, - }; +const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes'); function verifyPropTypes( - componentInterface: ComponentInterface, - viewConfig: Object, - nativePropsToIgnore?: ?Object, + viewConfig: $ReadOnly<{ + NativeProps: $ReadOnly<{ + [propName: string]: mixed, + }>, + propTypes: ?$ReadOnly<{ + [propName: string]: mixed, + }>, + uiViewClassName: string, + }>, + nativePropsToIgnore: ?$ReadOnly<{ + [propName: string]: boolean, + }>, ) { - if (!viewConfig) { - return; // This happens for UnimplementedView. - } - var componentName = - componentInterface.displayName || componentInterface.name || 'unknown'; - - var propTypes = componentInterface.propTypes; + const {NativeProps, propTypes, uiViewClassName} = viewConfig; - if (!propTypes) { + if (propTypes == null) { return; } - var nativeProps = viewConfig.NativeProps; - for (var prop in nativeProps) { + for (const propName in NativeProps) { if ( - !propTypes[prop] && - !ReactNativeStyleAttributes[prop] && - (!nativePropsToIgnore || !nativePropsToIgnore[prop]) + propTypes[propName] || + ReactNativeStyleAttributes[propName] || + (nativePropsToIgnore && nativePropsToIgnore[propName]) ) { - 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); + 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, + ); } } }