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

View File

@ -15,17 +15,14 @@ var EventEmitter = require('EventEmitter');
var Image = require('Image');
var NavigationContext = require('NavigationContext');
var React = require('React');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var RCTNavigatorManager = require('NativeModules').NavigatorManager;
var StyleSheet = require('StyleSheet');
var StaticContainer = require('StaticContainer.react');
var View = require('View');
var createReactNativeComponentClass =
require('createReactNativeComponentClass');
var requireNativeComponent = require('requireNativeComponent');
var invariant = require('invariant');
var logError = require('logError');
var merge = require('merge');
var TRANSITIONER_REF = 'transitionerRef';
@ -36,37 +33,6 @@ function getuid() {
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({
requestSchedulingNavigation: function(cb) {
RCTNavigatorManager.requestSchedulingJavaScriptNavigation(
@ -711,4 +677,7 @@ var styles = StyleSheet.create({
},
});
var RCTNavigator = requireNativeComponent('RCTNavigator');
var RCTNavigatorItem = requireNativeComponent('RCTNavItem');
module.exports = NavigatorIOS;

View File

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

View File

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

View File

@ -26,7 +26,6 @@ var flattenStyle = require('flattenStyle');
var invariant = require('invariant');
var requireNativeComponent = require('requireNativeComponent');
var resolveAssetSource = require('resolveAssetSource');
var verifyPropTypes = require('verifyPropTypes');
var warning = require('warning');
/**
@ -150,6 +149,12 @@ var Image = React.createClass({
},
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 defaultSource = (this.props.defaultSource && resolveAssetSource(this.props.defaultSource)) || {};
@ -180,7 +185,15 @@ var styles = StyleSheet.create({
},
});
var RCTImageView = requireNativeComponent('RCTImageView', null);
var RCTNetworkImageView = (NativeModules.NetworkImageViewManager) ? requireNativeComponent('RCTNetworkImageView', null) : RCTImageView;
var cfg = {
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;

View File

@ -27,19 +27,22 @@ var warning = require('warning');
* implementations. Config information is extracted from data exported from the
* RCTUIManager module. You should also wrap the native component in a
* 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`.
*
* 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`;
*
* Common types are lined up with the appropriate prop differs with
* `TypeToDifferMap`. Non-scalar types not in the map default to `deepDiffer`.
*/
import type { ComponentInterface } from 'verifyPropTypes';
function requireNativeComponent(
viewName: string,
wrapperComponent: ?Function
componentInterface?: ?ComponentInterface,
extraConfig?: ?{nativeOnly?: Object},
): Function {
var viewConfig = RCTUIManager[viewName];
if (!viewConfig || !viewConfig.NativeProps) {
@ -52,12 +55,17 @@ function requireNativeComponent(
};
viewConfig.uiViewClassName = viewName;
viewConfig.validAttributes = {};
viewConfig.propTypes = componentInterface && componentInterface.propTypes;
for (var key in nativeProps) {
var differ = TypeToDifferMap[nativeProps[key]];
viewConfig.validAttributes[key] = differ ? {diff: differ} : true;
}
if (__DEV__) {
wrapperComponent && verifyPropTypes(wrapperComponent, viewConfig);
componentInterface && verifyPropTypes(
componentInterface,
viewConfig,
extraConfig && extraConfig.nativeOnly
);
}
return createReactNativeComponentClass(viewConfig);
}

View File

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

View File

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