[ReactNative] cleanup native components

This commit is contained in:
Spencer Ahrens 2015-07-24 18:31:55 -07:00
parent 53222f0dda
commit f1bd1cbc94
8 changed files with 49 additions and 59 deletions

View File

@ -18,7 +18,6 @@ var StyleSheet = require('StyleSheet');
var View = require('View'); var View = require('View');
var requireNativeComponent = require('requireNativeComponent'); var requireNativeComponent = require('requireNativeComponent');
var verifyPropTypes = require('verifyPropTypes');
var GRAY = '#999999'; var GRAY = '#999999';
@ -99,15 +98,8 @@ var styles = StyleSheet.create({
var RCTActivityIndicatorView = requireNativeComponent( var RCTActivityIndicatorView = requireNativeComponent(
'RCTActivityIndicatorView', 'RCTActivityIndicatorView',
null
);
if (__DEV__) {
var nativeOnlyProps = {activityIndicatorViewStyle: true};
verifyPropTypes(
ActivityIndicatorIOS, ActivityIndicatorIOS,
RCTActivityIndicatorView.viewConfig, {nativeOnly: {activityIndicatorViewStyle: true}},
nativeOnlyProps
); );
}
module.exports = ActivityIndicatorIOS; module.exports = ActivityIndicatorIOS;

View File

@ -15,17 +15,14 @@ var EventEmitter = require('EventEmitter');
var Image = require('Image'); var Image = require('Image');
var NavigationContext = require('NavigationContext'); var NavigationContext = require('NavigationContext');
var React = require('React'); var React = require('React');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var RCTNavigatorManager = require('NativeModules').NavigatorManager; var RCTNavigatorManager = require('NativeModules').NavigatorManager;
var StyleSheet = require('StyleSheet'); var StyleSheet = require('StyleSheet');
var StaticContainer = require('StaticContainer.react'); var StaticContainer = require('StaticContainer.react');
var View = require('View'); var View = require('View');
var createReactNativeComponentClass = var requireNativeComponent = require('requireNativeComponent');
require('createReactNativeComponentClass');
var invariant = require('invariant'); var invariant = require('invariant');
var logError = require('logError'); var logError = require('logError');
var merge = require('merge');
var TRANSITIONER_REF = 'transitionerRef'; var TRANSITIONER_REF = 'transitionerRef';
@ -36,37 +33,6 @@ function getuid() {
return __uid++; return __uid++;
} }
var RCTNavigator = createReactNativeComponentClass({
validAttributes: merge(ReactNativeViewAttributes.UIView, {
requestedTopOfStack: true
}),
uiViewClassName: 'RCTNavigator',
});
var RCTNavigatorItem = createReactNativeComponentClass({
validAttributes: {
// TODO: Remove or fix the attributes that are not fully functional.
// NavigatorIOS does not use them all, because some are problematic
title: true,
barTintColor: true,
leftButtonIcon: true,
leftButtonTitle: true,
onNavLeftButtonTap: true,
rightButtonIcon: true,
rightButtonTitle: true,
onNavRightButtonTap: true,
backButtonIcon: true,
backButtonTitle: true,
tintColor: true,
translucent: true,
navigationBarHidden: true,
shadowHidden: true,
titleTextColor: true,
style: true,
},
uiViewClassName: 'RCTNavItem',
});
var NavigatorTransitionerIOS = React.createClass({ var NavigatorTransitionerIOS = React.createClass({
requestSchedulingNavigation: function(cb) { requestSchedulingNavigation: function(cb) {
RCTNavigatorManager.requestSchedulingJavaScriptNavigation( RCTNavigatorManager.requestSchedulingJavaScriptNavigation(
@ -711,4 +677,7 @@ var styles = StyleSheet.create({
}, },
}); });
var RCTNavigator = requireNativeComponent('RCTNavigator');
var RCTNavigatorItem = requireNativeComponent('RCTNavItem');
module.exports = NavigatorIOS; module.exports = NavigatorIOS;

View File

@ -19,7 +19,6 @@ var React = require('React');
var StyleSheet = require('StyleSheet'); var StyleSheet = require('StyleSheet');
var requireNativeComponent = require('requireNativeComponent'); var requireNativeComponent = require('requireNativeComponent');
var verifyPropTypes = require('verifyPropTypes');
/** /**
* Use `ProgressViewIOS` to render a UIProgressView on iOS. * Use `ProgressViewIOS` to render a UIProgressView on iOS.

View File

@ -18,7 +18,6 @@ var React = require('React');
var StyleSheet = require('StyleSheet'); var StyleSheet = require('StyleSheet');
var requireNativeComponent = require('requireNativeComponent'); var requireNativeComponent = require('requireNativeComponent');
var verifyPropTypes = require('verifyPropTypes');
type DefaultProps = { type DefaultProps = {
values: Array<string>; values: Array<string>;

View File

@ -26,7 +26,6 @@ var flattenStyle = require('flattenStyle');
var invariant = require('invariant'); var invariant = require('invariant');
var requireNativeComponent = require('requireNativeComponent'); var requireNativeComponent = require('requireNativeComponent');
var resolveAssetSource = require('resolveAssetSource'); var resolveAssetSource = require('resolveAssetSource');
var verifyPropTypes = require('verifyPropTypes');
var warning = require('warning'); var warning = require('warning');
/** /**
@ -150,6 +149,12 @@ var Image = React.createClass({
}, },
render: function() { render: function() {
for (var prop in cfg.nativeOnly) {
if (this.props[prop] !== undefined) {
console.warn('Prop `' + prop + ' = ' + this.props[prop] + '` should ' +
'not be set directly on Image.');
}
}
var source = resolveAssetSource(this.props.source) || {}; var source = resolveAssetSource(this.props.source) || {};
var defaultSource = (this.props.defaultSource && resolveAssetSource(this.props.defaultSource)) || {}; var defaultSource = (this.props.defaultSource && resolveAssetSource(this.props.defaultSource)) || {};
@ -180,7 +185,15 @@ var styles = StyleSheet.create({
}, },
}); });
var RCTImageView = requireNativeComponent('RCTImageView', null); var cfg = {
var RCTNetworkImageView = (NativeModules.NetworkImageViewManager) ? requireNativeComponent('RCTNetworkImageView', null) : RCTImageView; nativeOnly: {
src: true,
defaultImageSrc: true,
imageTag: true,
progressHandlerRegistered: true,
},
};
var RCTImageView = requireNativeComponent('RCTImageView', Image, cfg);
var RCTNetworkImageView = (NativeModules.NetworkImageViewManager) ? requireNativeComponent('RCTNetworkImageView', Image, cfg) : RCTImageView;
module.exports = Image; module.exports = Image;

View File

@ -27,19 +27,22 @@ var warning = require('warning');
* implementations. Config information is extracted from data exported from the * implementations. Config information is extracted from data exported from the
* RCTUIManager module. You should also wrap the native component in a * RCTUIManager module. You should also wrap the native component in a
* hand-written component with full propTypes definitions and other * hand-written component with full propTypes definitions and other
* documentation - pass the hand-written component in as `wrapperComponent` to * documentation - pass the hand-written component in as `componentInterface` to
* verify all the native props are documented via `propTypes`. * verify all the native props are documented via `propTypes`.
* *
* If some native props shouldn't be exposed in the wrapper interface, you can * If some native props shouldn't be exposed in the wrapper interface, you can
* pass null for `wrapperComponent` and call `verifyPropTypes` directly * pass null for `componentInterface` and call `verifyPropTypes` directly
* with `nativePropsToIgnore`; * with `nativePropsToIgnore`;
* *
* Common types are lined up with the appropriate prop differs with * Common types are lined up with the appropriate prop differs with
* `TypeToDifferMap`. Non-scalar types not in the map default to `deepDiffer`. * `TypeToDifferMap`. Non-scalar types not in the map default to `deepDiffer`.
*/ */
import type { ComponentInterface } from 'verifyPropTypes';
function requireNativeComponent( function requireNativeComponent(
viewName: string, viewName: string,
wrapperComponent: ?Function componentInterface?: ?ComponentInterface,
extraConfig?: ?{nativeOnly?: Object},
): Function { ): Function {
var viewConfig = RCTUIManager[viewName]; var viewConfig = RCTUIManager[viewName];
if (!viewConfig || !viewConfig.NativeProps) { if (!viewConfig || !viewConfig.NativeProps) {
@ -52,12 +55,17 @@ function requireNativeComponent(
}; };
viewConfig.uiViewClassName = viewName; viewConfig.uiViewClassName = viewName;
viewConfig.validAttributes = {}; viewConfig.validAttributes = {};
viewConfig.propTypes = componentInterface && componentInterface.propTypes;
for (var key in nativeProps) { for (var key in nativeProps) {
var differ = TypeToDifferMap[nativeProps[key]]; var differ = TypeToDifferMap[nativeProps[key]];
viewConfig.validAttributes[key] = differ ? {diff: differ} : true; viewConfig.validAttributes[key] = differ ? {diff: differ} : true;
} }
if (__DEV__) { if (__DEV__) {
wrapperComponent && verifyPropTypes(wrapperComponent, viewConfig); componentInterface && verifyPropTypes(
componentInterface,
viewConfig,
extraConfig && extraConfig.nativeOnly
);
} }
return createReactNativeComponentClass(viewConfig); return createReactNativeComponentClass(viewConfig);
} }

View File

@ -14,16 +14,24 @@
var ReactNativeStyleAttributes = require('ReactNativeStyleAttributes'); var ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
var View = require('View'); var View = require('View');
export type ComponentInterface = ReactClass<any, any, any> | {
name?: string;
displayName?: string;
propTypes: Object;
};
function verifyPropTypes( function verifyPropTypes(
component: Function, componentInterface: ComponentInterface,
viewConfig: Object, viewConfig: Object,
nativePropsToIgnore?: Object nativePropsToIgnore?: ?Object
) { ) {
if (!viewConfig) { if (!viewConfig) {
return; // This happens for UnimplementedView. return; // This happens for UnimplementedView.
} }
var componentName = component.name || component.displayName; var componentName = componentInterface.name ||
if (!component.propTypes) { componentInterface.displayName ||
'unknown';
if (!componentInterface.propTypes) {
throw new Error( throw new Error(
'`' + componentName + '` has no propTypes defined`' '`' + componentName + '` has no propTypes defined`'
); );
@ -31,7 +39,7 @@ function verifyPropTypes(
var nativeProps = viewConfig.NativeProps; var nativeProps = viewConfig.NativeProps;
for (var prop in nativeProps) { for (var prop in nativeProps) {
if (!component.propTypes[prop] && if (!componentInterface.propTypes[prop] &&
!View.propTypes[prop] && !View.propTypes[prop] &&
!ReactNativeStyleAttributes[prop] && !ReactNativeStyleAttributes[prop] &&
(!nativePropsToIgnore || !nativePropsToIgnore[prop])) { (!nativePropsToIgnore || !nativePropsToIgnore[prop])) {

View File

@ -18,6 +18,7 @@ var ReactNativeBaseComponent = require('ReactNativeBaseComponent');
type ReactNativeBaseComponentViewConfig = { type ReactNativeBaseComponentViewConfig = {
validAttributes: Object; validAttributes: Object;
uiViewClassName: string; uiViewClassName: string;
propTypes?: Object,
} }
/** /**
@ -36,6 +37,7 @@ var createReactNativeComponentClass = function(
}; };
Constructor.displayName = viewConfig.uiViewClassName; Constructor.displayName = viewConfig.uiViewClassName;
Constructor.viewConfig = viewConfig; Constructor.viewConfig = viewConfig;
Constructor.propTypes = viewConfig.propTypes;
Constructor.prototype = new ReactNativeBaseComponent(viewConfig); Constructor.prototype = new ReactNativeBaseComponent(viewConfig);
Constructor.prototype.constructor = Constructor; Constructor.prototype.constructor = Constructor;