Replaced View.propTypes with a static getter that warned about deprecation

Reviewed By: spicyj

Differential Revision: D4766860

fbshipit-source-id: c0ef46df58b6167178e801d9dbe481101c0dc773
This commit is contained in:
Brian Vaughn 2017-03-28 11:17:21 -07:00 committed by Facebook Github Bot
parent 777e80a2b7
commit 1129c6096d
4 changed files with 88 additions and 39 deletions

View File

@ -1854,14 +1854,24 @@ function createAnimatedComponent(Component: any): any {
return this._component; return this._component;
} }
} }
// 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 =
Component.__propTypesSecretDontUseThesePlease ||
Component.propTypes;
AnimatedComponent.propTypes = { AnimatedComponent.propTypes = {
style: function(props, propName, componentName) { style: function(props, propName, componentName) {
if (!Component.propTypes) { if (!propTypes) {
return; return;
} }
for (var key in ViewStylePropTypes) { for (var key in ViewStylePropTypes) {
if (!Component.propTypes[key] && props[key] !== undefined) { if (!propTypes[key] && props[key] !== undefined) {
console.warn( console.warn(
'You are setting the style `{ ' + key + ': ... }` as a prop. You ' + 'You are setting the style `{ ' + key + ': ... }` as a prop. You ' +
'should nest it in a style object. ' + 'should nest it in a style object. ' +

View File

@ -87,6 +87,21 @@ const View = React.createClass({
// values had to be hardcoded. // values had to be hardcoded.
mixins: [NativeMethodsMixin], mixins: [NativeMethodsMixin],
// `propTypes` should not be accessed directly on View since this wrapper only
// exists for DEV mode. However it's important for them to be declared.
// If the object passed to `createClass` specifies `propTypes`, Flow will
// create a static type from it. This property will be over-written below with
// a warn-on-use getter though.
// TODO (bvaughn) Remove the warn-on-use comment after April 1.
propTypes: ViewPropTypes,
// ReactElementValidator will (temporarily) use this private accessor when
// detected to avoid triggering the warning message.
// TODO (bvaughn) Remove this after April 1 ReactNative RC is tagged.
statics: {
__propTypesSecretDontUseThesePlease: ViewPropTypes
},
/** /**
* `NativeMethodsMixin` will look for this when invoking `setNativeProps`. We * `NativeMethodsMixin` will look for this when invoking `setNativeProps`. We
* make `this` look like an actual native component class. * make `this` look like an actual native component class.
@ -96,11 +111,6 @@ const View = React.createClass({
validAttributes: ReactNativeViewAttributes.RCTView validAttributes: ReactNativeViewAttributes.RCTView
}, },
// TODO (bvaughn) Replace this with a deprecated getter warning. This object
// should be accessible via a separate import. It will not be available in
// production mode in the future and so should not be directly accessed.
propTypes: ViewPropTypes,
contextTypes: { contextTypes: {
isInAParentText: React.PropTypes.bool, isInAParentText: React.PropTypes.bool,
}, },
@ -122,57 +132,64 @@ const View = React.createClass({
// be supported with React fiber. This warning message will go away in the next // be supported with React fiber. This warning message will go away in the next
// ReactNative release. Use defineProperty() rather than createClass() statics // ReactNative release. Use defineProperty() rather than createClass() statics
// because the mixin process auto-triggers the 1-time warning message. // because the mixin process auto-triggers the 1-time warning message.
// TODO (bvaughn) Remove these warning messages after the April ReactNative tag. // TODO (bvaughn) Remove this after April 1 ReactNative RC is tagged.
function mixinStatics (target) { function mixinStatics (target) {
let warnedAboutAccessibilityTraits = false; let warnedAboutAccessibilityTraits = false;
let warnedAboutAccessibilityComponentType = false; let warnedAboutAccessibilityComponentType = false;
let warnedAboutForceTouchAvailable = false; let warnedAboutForceTouchAvailable = false;
let warnedAboutPropTypes = false;
// $FlowFixMe https://github.com/facebook/flow/issues/285 // $FlowFixMe https://github.com/facebook/flow/issues/285
Object.defineProperty(target, 'AccessibilityTraits', { Object.defineProperty(target, 'AccessibilityTraits', {
get: function() { get: function() {
if (!warnedAboutAccessibilityTraits) {
warnedAboutAccessibilityTraits = true;
warning( warning(
false, warnedAboutAccessibilityTraits,
'View.AccessibilityTraits has been deprecated and will be ' + 'View.AccessibilityTraits has been deprecated and will be ' +
'removed in a future version of ReactNative. Use ' + 'removed in a future version of ReactNative. Use ' +
'ViewAccessibility.AccessibilityTraits instead.' 'ViewAccessibility.AccessibilityTraits instead.'
); );
} warnedAboutAccessibilityTraits = true;
return AccessibilityTraits; return AccessibilityTraits;
} }
}); });
// $FlowFixMe https://github.com/facebook/flow/issues/285 // $FlowFixMe https://github.com/facebook/flow/issues/285
Object.defineProperty(target, 'AccessibilityComponentType', { Object.defineProperty(target, 'AccessibilityComponentType', {
get: function() { get: function() {
if (!warnedAboutAccessibilityComponentType) {
warnedAboutAccessibilityComponentType = true;
warning( warning(
false, warnedAboutAccessibilityComponentType,
'View.AccessibilityComponentType has been deprecated and will be ' + 'View.AccessibilityComponentType has been deprecated and will be ' +
'removed in a future version of ReactNative. Use ' + 'removed in a future version of ReactNative. Use ' +
'ViewAccessibility.AccessibilityComponentTypes instead.' 'ViewAccessibility.AccessibilityComponentTypes instead.'
); );
} warnedAboutAccessibilityComponentType = true;
return AccessibilityComponentTypes; return AccessibilityComponentTypes;
} }
}); });
// $FlowFixMe https://github.com/facebook/flow/issues/285 // $FlowFixMe https://github.com/facebook/flow/issues/285
Object.defineProperty(target, 'forceTouchAvailable', { Object.defineProperty(target, 'forceTouchAvailable', {
get: function() { get: function() {
if (!warnedAboutForceTouchAvailable) {
warnedAboutForceTouchAvailable = true;
warning( warning(
false, warnedAboutForceTouchAvailable,
'View.forceTouchAvailable has been deprecated and will be removed ' + 'View.forceTouchAvailable has been deprecated and will be removed ' +
'in a future version of ReactNative. Use ' + 'in a future version of ReactNative. Use ' +
'NativeModules.PlatformConstants.forceTouchAvailable instead.' 'NativeModules.PlatformConstants.forceTouchAvailable instead.'
); );
} warnedAboutForceTouchAvailable = true;
return forceTouchAvailable; return forceTouchAvailable;
} }
}); });
// $FlowFixMe https://github.com/facebook/flow/issues/285
Object.defineProperty(target, 'propTypes', {
get: function() {
warning(
warnedAboutPropTypes,
'View.propTypes has been deprecated and will be removed in a future ' +
'version of ReactNative. Use ViewPropTypes instead.'
);
warnedAboutPropTypes = true;
return ViewPropTypes;
}
});
} }
const RCTView = requireNativeComponent('RCTView', View, { const RCTView = requireNativeComponent('RCTView', View, {

View File

@ -55,7 +55,20 @@ function requireNativeComponent(
viewConfig.uiViewClassName = viewName; viewConfig.uiViewClassName = viewName;
viewConfig.validAttributes = {}; viewConfig.validAttributes = {};
viewConfig.propTypes = componentInterface && componentInterface.propTypes;
// 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
if (componentInterface) {
viewConfig.propTypes =
typeof componentInterface.__propTypesSecretDontUseThesePlease === 'object'
? componentInterface.__propTypesSecretDontUseThesePlease
: componentInterface.propTypes;
} else {
viewConfig.propTypes = null;
}
// The ViewConfig doesn't contain any props inherited from the view manager's // The ViewConfig doesn't contain any props inherited from the view manager's
// superclass, so we manually merge in the RCTView ones. Other inheritance // superclass, so we manually merge in the RCTView ones. Other inheritance

View File

@ -32,7 +32,16 @@ function verifyPropTypes(
componentInterface.name || componentInterface.name ||
'unknown'; 'unknown';
if (!componentInterface.propTypes) { // 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) {
throw new Error( throw new Error(
'`' + componentName + '` has no propTypes defined`' '`' + componentName + '` has no propTypes defined`'
); );
@ -40,11 +49,11 @@ function verifyPropTypes(
var nativeProps = viewConfig.NativeProps; var nativeProps = viewConfig.NativeProps;
for (var prop in nativeProps) { for (var prop in nativeProps) {
if (!componentInterface.propTypes[prop] && if (!propTypes[prop] &&
!ReactNativeStyleAttributes[prop] && !ReactNativeStyleAttributes[prop] &&
(!nativePropsToIgnore || !nativePropsToIgnore[prop])) { (!nativePropsToIgnore || !nativePropsToIgnore[prop])) {
var message; var message;
if (componentInterface.propTypes.hasOwnProperty(prop)) { if (propTypes.hasOwnProperty(prop)) {
message = '`' + componentName + '` has incorrectly defined propType for native prop `' + message = '`' + componentName + '` has incorrectly defined propType for native prop `' +
viewConfig.uiViewClassName + '.' + prop + '` of native type `' + nativeProps[prop]; viewConfig.uiViewClassName + '.' + prop + '` of native type `' + nativeProps[prop];
} else { } else {