mirror of
https://github.com/status-im/react-native.git
synced 2025-01-26 17:30:25 +00:00
Add a deprecatedPropType module to show deprecation warnings
Summary: To allow smoother API changes for users we often deprecate props and keep them around for a while before removing them. Right now it is all done manually, this adds a consistent way to show a warning when using a deprecated prop. This also adds a deprecation warning of the website generated from the deprecatedPropType. <img width="643" alt="screen shot 2016-01-26 at 7 43 08 pm" src="https://cloud.githubusercontent.com/assets/2677334/12600172/7af28fb0-c465-11e5-85e5-3786852bf522.png"> It also changes places where we added the warnings manually to use deprecatedPropType instead. Closes https://github.com/facebook/react-native/pull/5566 Reviewed By: svcscm Differential Revision: D2874629 Pulled By: nicklockwood fb-gh-sync-id: c3c63bae7bbec26cc146029abd9aa5efbe73f795
This commit is contained in:
parent
8de86a0d65
commit
1c6e837504
@ -22,6 +22,7 @@ const React = require('React');
|
||||
const StyleSheet = require('StyleSheet');
|
||||
const View = require('View');
|
||||
|
||||
const deprecatedPropType = require('deprecatedPropType');
|
||||
const processColor = require('processColor');
|
||||
const resolveAssetSource = require('resolveAssetSource');
|
||||
const requireNativeComponent = require('requireNativeComponent');
|
||||
@ -64,7 +65,7 @@ const MapView = React.createClass({
|
||||
* @platform ios
|
||||
*/
|
||||
followUserLocation: React.PropTypes.bool,
|
||||
|
||||
|
||||
/**
|
||||
* If `false` points of interest won't be displayed on the map.
|
||||
* Default value is `true`.
|
||||
@ -160,7 +161,7 @@ const MapView = React.createClass({
|
||||
* Whether the pin drop should be animated or not
|
||||
*/
|
||||
animateDrop: React.PropTypes.bool,
|
||||
|
||||
|
||||
/**
|
||||
* Whether the pin should be draggable or not
|
||||
*/
|
||||
@ -168,7 +169,7 @@ const MapView = React.createClass({
|
||||
|
||||
/**
|
||||
* Event that fires when the annotation drag state changes.
|
||||
*/
|
||||
*/
|
||||
onDragStateChange: React.PropTypes.func,
|
||||
|
||||
/**
|
||||
@ -213,11 +214,22 @@ const MapView = React.createClass({
|
||||
/**
|
||||
* Deprecated. Use the left/right/detailsCalloutView props instead.
|
||||
*/
|
||||
hasLeftCallout: React.PropTypes.bool,
|
||||
hasRightCallout: React.PropTypes.bool,
|
||||
onLeftCalloutPress: React.PropTypes.func,
|
||||
onRightCalloutPress: React.PropTypes.func,
|
||||
|
||||
hasLeftCallout: deprecatedPropType(
|
||||
React.PropTypes.bool,
|
||||
'Use `leftCalloutView` instead.'
|
||||
),
|
||||
hasRightCallout: deprecatedPropType(
|
||||
React.PropTypes.bool,
|
||||
'Use `rightCalloutView` instead.'
|
||||
),
|
||||
onLeftCalloutPress: deprecatedPropType(
|
||||
React.PropTypes.func,
|
||||
'Use `leftCalloutView` instead.'
|
||||
),
|
||||
onRightCalloutPress: deprecatedPropType(
|
||||
React.PropTypes.func,
|
||||
'Use `rightCalloutView` instead.'
|
||||
),
|
||||
})),
|
||||
|
||||
/**
|
||||
@ -335,18 +347,7 @@ const MapView = React.createClass({
|
||||
style: [styles.calloutView, detailCalloutView.props.style || {}]
|
||||
}));
|
||||
}
|
||||
if (__DEV__) {
|
||||
['hasLeftCallout', 'onLeftCalloutPress'].forEach(key => {
|
||||
if (annotation[key]) {
|
||||
console.warn('`' + key + '` is deprecated. Use leftCalloutView instead.');
|
||||
}
|
||||
});
|
||||
['hasRightCallout', 'onRightCalloutPress'].forEach(key => {
|
||||
if (annotation[key]) {
|
||||
console.warn('`' + key + '` is deprecated. Use rightCalloutView instead.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let result = {
|
||||
...annotation,
|
||||
tintColor: tintColor && processColor(tintColor),
|
||||
|
@ -25,6 +25,7 @@ var View = require('View');
|
||||
var ViewStylePropTypes = require('ViewStylePropTypes');
|
||||
|
||||
var deepDiffer = require('deepDiffer');
|
||||
var deprecatedPropType = require('deprecatedPropType');
|
||||
var dismissKeyboard = require('dismissKeyboard');
|
||||
var flattenStyle = require('flattenStyle');
|
||||
var insetsDiffer = require('insetsDiffer');
|
||||
@ -321,10 +322,12 @@ var ScrollView = React.createClass({
|
||||
refreshControl: PropTypes.element,
|
||||
|
||||
/**
|
||||
* Deprecated - use `refreshControl` property instead.
|
||||
* @platform ios
|
||||
*/
|
||||
onRefreshStart: PropTypes.func,
|
||||
onRefreshStart: deprecatedPropType(
|
||||
PropTypes.func,
|
||||
'Use the `refreshControl` prop instead.'
|
||||
),
|
||||
},
|
||||
|
||||
mixins: [ScrollResponder.Mixin],
|
||||
@ -464,7 +467,6 @@ var ScrollView = React.createClass({
|
||||
|
||||
var onRefreshStart = this.props.onRefreshStart;
|
||||
if (onRefreshStart) {
|
||||
console.warn('onRefreshStart is deprecated. Use the refreshControl prop instead.');
|
||||
// this is necessary because if we set it on props, even when empty,
|
||||
// it'll trigger the default pull-to-refresh behavior on native.
|
||||
props.onRefreshStart =
|
||||
|
@ -42,6 +42,7 @@ var TimerMixin = require('react-timer-mixin');
|
||||
var View = require('View');
|
||||
|
||||
var clamp = require('clamp');
|
||||
var deprecatedPropType = require('deprecatedPropType');
|
||||
var flattenStyle = require('flattenStyle');
|
||||
var invariant = require('invariant');
|
||||
var rebound = require('rebound');
|
||||
@ -224,21 +225,21 @@ var Navigator = React.createClass({
|
||||
initialRouteStack: PropTypes.arrayOf(PropTypes.object),
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Use `navigationContext.addListener('willfocus', callback)` instead.
|
||||
*
|
||||
* Will emit the target route upon mounting and before each nav transition
|
||||
*/
|
||||
onWillFocus: PropTypes.func,
|
||||
onWillFocus: deprecatedPropType(
|
||||
PropTypes.func,
|
||||
"Use `navigationContext.addListener('willfocus', callback)` instead."
|
||||
),
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Use `navigationContext.addListener('didfocus', callback)` instead.
|
||||
*
|
||||
* Will be called with the new route of each scene after the transition is
|
||||
* complete or after the initial mounting
|
||||
*/
|
||||
onDidFocus: PropTypes.func,
|
||||
onDidFocus: deprecatedPropType(
|
||||
PropTypes.func,
|
||||
"Use `navigationContext.addListener('didfocus', callback)` instead."
|
||||
),
|
||||
|
||||
/**
|
||||
* Optionally provide a navigation bar that persists across scene
|
||||
|
@ -12,6 +12,7 @@
|
||||
'use strict';
|
||||
|
||||
var ReactPropTypes = require('ReactPropTypes');
|
||||
var deprecatedPropType = require('deprecatedPropType');
|
||||
|
||||
var ArrayOfNumberPropType = ReactPropTypes.arrayOf(ReactPropTypes.number);
|
||||
|
||||
@ -49,11 +50,11 @@ var TransformPropTypes = {
|
||||
transformMatrix: TransformMatrixPropType,
|
||||
|
||||
/* Deprecated transform props used on Android only */
|
||||
scaleX: ReactPropTypes.number,
|
||||
scaleY: ReactPropTypes.number,
|
||||
rotation: ReactPropTypes.number,
|
||||
translateX: ReactPropTypes.number,
|
||||
translateY: ReactPropTypes.number,
|
||||
scaleX: deprecatedPropType(ReactPropTypes.number, 'Use the transform prop instead.'),
|
||||
scaleY: deprecatedPropType(ReactPropTypes.number, 'Use the transform prop instead.'),
|
||||
rotation: deprecatedPropType(ReactPropTypes.number, 'Use the transform prop instead.'),
|
||||
translateX: deprecatedPropType(ReactPropTypes.number, 'Use the transform prop instead.'),
|
||||
translateY: deprecatedPropType(ReactPropTypes.number, 'Use the transform prop instead.'),
|
||||
};
|
||||
|
||||
module.exports = TransformPropTypes;
|
||||
|
33
Libraries/Utilities/deprecatedPropType.js
Normal file
33
Libraries/Utilities/deprecatedPropType.js
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule deprecatedPropType
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const UIManager = require('UIManager');
|
||||
|
||||
/**
|
||||
* Adds a deprecation warning when the prop is used.
|
||||
*/
|
||||
function deprecatedPropType(
|
||||
propType: ReactPropsCheckType,
|
||||
explanation: string
|
||||
): ReactPropsCheckType {
|
||||
return function validate(props, propName, componentName) {
|
||||
// Don't warn for native components.
|
||||
if (!UIManager[componentName] && props[propName] !== undefined) {
|
||||
console.warn(`\`${propName}\` supplied to \`${componentName}\` has been deprecated. ${explanation}`);
|
||||
}
|
||||
|
||||
return propType(props, propName, componentName);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = deprecatedPropType;
|
@ -119,6 +119,15 @@ var ComponentDoc = React.createClass({
|
||||
{renderType(prop.type)}
|
||||
</span>}
|
||||
</Header>
|
||||
{prop.deprecationMessage && <div className="deprecated">
|
||||
<div className="deprecatedTitle">
|
||||
<img className="deprecatedIcon" src="/react-native/img/Warning.png" />
|
||||
<span>Deprecated</span>
|
||||
</div>
|
||||
<div className="deprecatedMessage">
|
||||
<Marked>{prop.deprecationMessage}</Marked>
|
||||
</div>
|
||||
</div>}
|
||||
{prop.type && prop.type.name === 'stylesheet' &&
|
||||
this.renderStylesheetProps(prop.type.value)}
|
||||
{prop.description && <Marked>{prop.description}</Marked>}
|
||||
|
@ -6,6 +6,7 @@ function stylePropTypeHandler(documentation, path) {
|
||||
if (!propTypesPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
propTypesPath = docgen.utils.resolveToValue(propTypesPath);
|
||||
if (!propTypesPath || propTypesPath.node.type !== 'ObjectExpression') {
|
||||
return;
|
||||
@ -34,6 +35,43 @@ function stylePropTypeHandler(documentation, path) {
|
||||
});
|
||||
}
|
||||
|
||||
function deprecatedPropTypeHandler(documentation, path) {
|
||||
var propTypesPath = docgen.utils.getMemberValuePath(path, 'propTypes');
|
||||
if (!propTypesPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
propTypesPath = docgen.utils.resolveToValue(propTypesPath);
|
||||
if (!propTypesPath || propTypesPath.node.type !== 'ObjectExpression') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Checks for deprecatedPropType function and add deprecation info.
|
||||
propTypesPath.get('properties').each(function(propertyPath) {
|
||||
var valuePath = docgen.utils.resolveToValue(propertyPath.get('value'));
|
||||
// If it's a call to deprecatedPropType, do stuff
|
||||
if (valuePath.node.type !== 'CallExpression' ||
|
||||
valuePath.node.callee.name !== 'deprecatedPropType') {
|
||||
return;
|
||||
}
|
||||
var propDescriptor = documentation.getPropDescriptor(
|
||||
docgen.utils.getPropertyName(propertyPath)
|
||||
);
|
||||
// The 2nd argument of deprecatedPropType is the deprecation message.
|
||||
// Used printValue to get the string otherwise there was issues with template
|
||||
// strings.
|
||||
propDescriptor.deprecationMessage = docgen.utils
|
||||
.printValue(valuePath.get('arguments', 1))
|
||||
// Remove the quotes printValue adds.
|
||||
.slice(1, -1);
|
||||
|
||||
// Get the actual prop type.
|
||||
propDescriptor.type = docgen.utils.getPropType(
|
||||
valuePath.get('arguments', 0)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function findExportedOrFirst(node, recast) {
|
||||
return docgen.resolver.findExportedComponentDefinition(node, recast) ||
|
||||
docgen.resolver.findAllComponentDefinitions(node, recast)[0];
|
||||
@ -86,5 +124,6 @@ function findExportedObject(ast, recast) {
|
||||
}
|
||||
|
||||
exports.stylePropTypeHandler = stylePropTypeHandler;
|
||||
exports.deprecatedPropTypeHandler = deprecatedPropTypeHandler;
|
||||
exports.findExportedOrFirst = findExportedOrFirst;
|
||||
exports.findExportedObject = findExportedObject;
|
||||
|
@ -149,7 +149,10 @@ function renderComponent(filepath) {
|
||||
var json = docgen.parse(
|
||||
fs.readFileSync(filepath),
|
||||
docgenHelpers.findExportedOrFirst,
|
||||
docgen.defaultHandlers.concat(docgenHelpers.stylePropTypeHandler)
|
||||
docgen.defaultHandlers.concat([
|
||||
docgenHelpers.stylePropTypeHandler,
|
||||
docgenHelpers.deprecatedPropTypeHandler,
|
||||
])
|
||||
);
|
||||
|
||||
return componentsToMarkdown('component', json, filepath, n++, styleDocs);
|
||||
|
@ -1096,6 +1096,28 @@ div[data-twttr-id] iframe {
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.deprecated {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.deprecatedTitle {
|
||||
margin-bottom: 6px;
|
||||
line-height: 18px;
|
||||
font-weight: bold;
|
||||
color: #ffa500;
|
||||
}
|
||||
|
||||
.deprecatedIcon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 8px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.deprecatedMessage {
|
||||
margin-left: 26px;
|
||||
}
|
||||
|
||||
.edit-github {
|
||||
font-size: 15px;
|
||||
font-weight: normal;
|
||||
|
0
website/src/react-native/img/Warning.png
Normal file
0
website/src/react-native/img/Warning.png
Normal file
Loading…
x
Reference in New Issue
Block a user