mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-24 04:16:00 +08:00
Updates from Tue 31 Mar
- Bugfix/require module regexp | Amjad Masad - [ReactNative] RCTView's shadowOffset is of float type, not CGFloat | Kevin Gozali - Fix WebView automaticallyAdjustContentInsets error | Spencer Ahrens - [react-native] map view - add onTouch** props | Jiajie Zhu - [react-native] Fix documentation extraction for View | Ben Alpert - [ReactNative] Add few hints in the UI | Alex Kotliarskyi - Adding `scrollWithoutAnimationTo` method for ScrollViews | Felix Oghina - [ScrollView] Add "bounces" property to ScrollView propTypes | Spencer Ahrens - Fix a crash in RCTAsyncLocalStorage when the value is not a string. | Spencer Ahrens - [ReactNative] Remove global MutationObserver to fix Bluebird feature detection | Christopher Chedeau - [catalyst] fix typo | Jiajie Zhu - [react-packager] check-in bluebird | Amjad Masad - [react-native] v0.3.1 | Amjad Masad - [Pod] Preserve header directory structure | Alex Akers - [react-native] Bring React.render behavior in line with web | Ben Alpert - Expose html prop on WebView | Spencer Ahrens - missing '.' in ListView.DataSource example | Christopher Chedeau - [react-native] Support returning null from a component | Ben Alpert - [react-native] Fix race condition in removeSubviewsFromContainerWithID: | Ben Alpert
This commit is contained in:
@@ -147,6 +147,9 @@ var MapView = React.createClass({
|
||||
legalLabelInsets={this.props.legalLabelInsets}
|
||||
onChange={this._onChange}
|
||||
onTouchStart={this.props.onTouchStart}
|
||||
onTouchMove={this.props.onTouchMove}
|
||||
onTouchEnd={this.props.onTouchEnd}
|
||||
onTouchCancel={this.props.onTouchCancel}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -59,13 +59,20 @@ var ScrollView = React.createClass({
|
||||
contentOffset: PointPropType, // zeros
|
||||
onScroll: PropTypes.func,
|
||||
onScrollAnimationEnd: PropTypes.func,
|
||||
scrollEnabled: PropTypes.bool, // tre
|
||||
scrollEnabled: PropTypes.bool, // true
|
||||
scrollIndicatorInsets: EdgeInsetsPropType, // zeros
|
||||
showsHorizontalScrollIndicator: PropTypes.bool,
|
||||
showsVerticalScrollIndicator: PropTypes.bool,
|
||||
style: StyleSheetPropType(ViewStylePropTypes),
|
||||
scrollEventThrottle: PropTypes.number, // null
|
||||
|
||||
/**
|
||||
* When true, the scroll view bounces when it reaches the end of the
|
||||
* content if the content is larger then the scroll view along the axis of
|
||||
* the scroll direction. When false, it disables all bouncing even if
|
||||
* the `alwaysBounce*` props are true. The default value is true.
|
||||
*/
|
||||
bounces: PropTypes.bool,
|
||||
/**
|
||||
* When true, the scroll view bounces horizontally when it reaches the end
|
||||
* even if the content is smaller than the scroll view itself. The default
|
||||
@@ -195,6 +202,14 @@ var ScrollView = React.createClass({
|
||||
);
|
||||
},
|
||||
|
||||
scrollWithoutAnimationTo: function(destY?: number, destX?: number) {
|
||||
RCTUIManager.scrollWithoutAnimationTo(
|
||||
this.getNodeHandle(),
|
||||
destX || 0,
|
||||
destY || 0
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var contentContainerStyle = [
|
||||
this.props.horizontal && styles.contentContainerHorizontal,
|
||||
@@ -308,6 +323,7 @@ var validAttributes = {
|
||||
alwaysBounceHorizontal: true,
|
||||
alwaysBounceVertical: true,
|
||||
automaticallyAdjustContentInsets: true,
|
||||
bounces: true,
|
||||
centerContent: true,
|
||||
contentInset: {diff: insetsDiffer},
|
||||
contentOffset: {diff: pointsDiffer},
|
||||
|
||||
@@ -60,7 +60,8 @@ var WebView = React.createClass({
|
||||
propTypes: {
|
||||
renderError: PropTypes.func.isRequired, // view to show if there's an error
|
||||
renderLoading: PropTypes.func.isRequired, // loading indicator to show
|
||||
url: PropTypes.string.isRequired,
|
||||
url: PropTypes.string,
|
||||
html: PropTypes.string,
|
||||
automaticallyAdjustContentInsets: PropTypes.bool,
|
||||
shouldInjectAJAXHandler: PropTypes.bool,
|
||||
contentInset: EdgeInsetsPropType,
|
||||
@@ -115,6 +116,7 @@ var WebView = React.createClass({
|
||||
key="webViewKey"
|
||||
style={webViewStyles}
|
||||
url={this.props.url}
|
||||
html={this.props.html}
|
||||
shouldInjectAJAXHandler={this.props.shouldInjectAJAXHandler}
|
||||
contentInset={this.props.contentInset}
|
||||
automaticallyAdjustContentInsets={this.props.automaticallyAdjustContentInsets}
|
||||
@@ -182,6 +184,7 @@ var WebView = React.createClass({
|
||||
var RCTWebView = createReactIOSNativeComponentClass({
|
||||
validAttributes: merge(ReactIOSViewAttributes.UIView, {
|
||||
url: true,
|
||||
html: true,
|
||||
contentInset: {diff: insetsDiffer},
|
||||
automaticallyAdjustContentInsets: true,
|
||||
shouldInjectAJAXHandler: true
|
||||
|
||||
@@ -60,6 +60,10 @@ function setupDocumentShim() {
|
||||
if (GLOBAL.document) {
|
||||
GLOBAL.document.createElement = null;
|
||||
}
|
||||
|
||||
// There is no DOM so MutationObserver doesn't make sense. It is used
|
||||
// as feature detection in Bluebird Promise implementation
|
||||
GLOBAL.MutationObserver = undefined;
|
||||
}
|
||||
|
||||
function handleErrorWithRedBox(e) {
|
||||
|
||||
@@ -67,8 +67,12 @@ var augmentElement = function(element: ReactElement) {
|
||||
return element;
|
||||
};
|
||||
|
||||
var render = function(component: ReactComponent, mountInto: number) {
|
||||
ReactIOSMount.renderComponent(component, mountInto);
|
||||
var render = function(
|
||||
element: ReactElement,
|
||||
mountInto: number,
|
||||
callback?: ?(() => void)
|
||||
): ?ReactComponent {
|
||||
return ReactIOSMount.renderComponent(element, mountInto, callback);
|
||||
};
|
||||
|
||||
var ReactIOS = {
|
||||
|
||||
@@ -24,6 +24,7 @@ var NodeHandle = require('NodeHandle');
|
||||
var ReactClass = require('ReactClass');
|
||||
var ReactComponentEnvironment = require('ReactComponentEnvironment');
|
||||
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
|
||||
var ReactEmptyComponent = require('ReactEmptyComponent');
|
||||
var ReactInstanceHandles = require('ReactInstanceHandles');
|
||||
var ReactIOSComponentEnvironment = require('ReactIOSComponentEnvironment');
|
||||
var ReactIOSComponentMixin = require('ReactIOSComponentMixin');
|
||||
@@ -36,6 +37,8 @@ var ReactUpdates = require('ReactUpdates');
|
||||
var ResponderEventPlugin = require('ResponderEventPlugin');
|
||||
var UniversalWorkerNodeHandle = require('UniversalWorkerNodeHandle');
|
||||
|
||||
var createReactIOSNativeComponentClass = require('createReactIOSNativeComponentClass');
|
||||
|
||||
// Just to ensure this gets packaged, since its only caller is from Native.
|
||||
require('RCTEventEmitter');
|
||||
require('RCTLog');
|
||||
@@ -77,6 +80,13 @@ function inject() {
|
||||
ReactIOSComponentEnvironment
|
||||
);
|
||||
|
||||
// Can't import View here because it depends on React to make its composite
|
||||
var RCTView = createReactIOSNativeComponentClass({
|
||||
validAttributes: {},
|
||||
uiViewClassName: 'RCTView',
|
||||
});
|
||||
ReactEmptyComponent.injection.injectEmptyComponent(RCTView);
|
||||
|
||||
EventPluginUtils.injection.injectMount(ReactIOSMount);
|
||||
|
||||
ReactClass.injection.injectMixin(ReactIOSComponentMixin);
|
||||
|
||||
@@ -16,13 +16,13 @@ var RCTUIManager = require('NativeModules').UIManager;
|
||||
var ReactIOSTagHandles = require('ReactIOSTagHandles');
|
||||
var ReactPerf = require('ReactPerf');
|
||||
var ReactReconciler = require('ReactReconciler');
|
||||
var ReactUpdateQueue = require('ReactUpdateQueue');
|
||||
var ReactUpdates = require('ReactUpdates');
|
||||
|
||||
var emptyObject = require('emptyObject');
|
||||
var instantiateReactComponent = require('instantiateReactComponent');
|
||||
var invariant = require('invariant');
|
||||
|
||||
var TOP_ROOT_NODE_IDS = {};
|
||||
var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
|
||||
|
||||
function instanceNumberToChildRootID(rootNodeID, instanceNumber) {
|
||||
return rootNodeID + '[' + instanceNumber + ']';
|
||||
@@ -85,10 +85,26 @@ var ReactIOSMount = {
|
||||
* @param {containerTag} containerView Handle to native view tag
|
||||
*/
|
||||
renderComponent: function(
|
||||
descriptor: ReactComponent,
|
||||
containerTag: number
|
||||
) {
|
||||
var instance = instantiateReactComponent(descriptor);
|
||||
nextElement: ReactElement,
|
||||
containerTag: number,
|
||||
callback?: ?(() => void)
|
||||
): ?ReactComponent {
|
||||
var topRootNodeID = ReactIOSTagHandles.tagToRootNodeID[containerTag];
|
||||
if (topRootNodeID) {
|
||||
var prevComponent = ReactIOSMount._instancesByContainerID[topRootNodeID];
|
||||
if (prevComponent) {
|
||||
var prevElement = prevComponent._currentElement;
|
||||
if (shouldUpdateReactComponent(prevElement, nextElement)) {
|
||||
ReactUpdateQueue.enqueueElementInternal(prevComponent, nextElement);
|
||||
if (callback) {
|
||||
ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);
|
||||
}
|
||||
return prevComponent;
|
||||
} else {
|
||||
ReactIOSMount.unmountComponentAtNode(containerTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ReactIOSTagHandles.reactTagIsNativeTopRootID(containerTag)) {
|
||||
console.error('You cannot render into anything but a top root');
|
||||
@@ -100,13 +116,14 @@ var ReactIOSMount = {
|
||||
topRootNodeID,
|
||||
containerTag
|
||||
);
|
||||
TOP_ROOT_NODE_IDS[topRootNodeID] = true;
|
||||
|
||||
var instance = instantiateReactComponent(nextElement);
|
||||
ReactIOSMount._instancesByContainerID[topRootNodeID] = instance;
|
||||
|
||||
var childRootNodeID = instanceNumberToChildRootID(
|
||||
topRootNodeID,
|
||||
ReactIOSMount.instanceCount++
|
||||
);
|
||||
ReactIOSMount._instancesByContainerID[topRootNodeID] = instance;
|
||||
|
||||
// The initial render is synchronous but any updates that happen during
|
||||
// rendering, in componentWillMount or componentDidMount, will be batched
|
||||
@@ -118,6 +135,11 @@ var ReactIOSMount = {
|
||||
childRootNodeID,
|
||||
topRootNodeID
|
||||
);
|
||||
var component = instance.getPublicInstance();
|
||||
if (callback) {
|
||||
callback.call(component);
|
||||
}
|
||||
return component;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -170,20 +192,18 @@ var ReactIOSMount = {
|
||||
* component at this time.
|
||||
*/
|
||||
unmountComponentAtNode: function(containerTag: number): bool {
|
||||
var containerID = ReactIOSTagHandles.tagToRootNodeID[containerTag];
|
||||
if (!ReactIOSTagHandles.reactTagIsNativeTopRootID(containerTag)) {
|
||||
console.error('You cannot render into anything but a top root');
|
||||
return;
|
||||
}
|
||||
|
||||
invariant(
|
||||
TOP_ROOT_NODE_IDS[containerID],
|
||||
'We only currently support removing components from the root node'
|
||||
);
|
||||
var containerID = ReactIOSTagHandles.tagToRootNodeID[containerTag];
|
||||
var instance = ReactIOSMount._instancesByContainerID[containerID];
|
||||
if (!instance) {
|
||||
console.error('Tried to unmount a component that does not exist');
|
||||
return false;
|
||||
}
|
||||
ReactIOSMount.unmountComponentFromNode(instance, containerID);
|
||||
delete ReactIOSMount._instancesByContainerID[containerID];
|
||||
delete TOP_ROOT_NODE_IDS[containerID];
|
||||
return true;
|
||||
},
|
||||
|
||||
@@ -200,10 +220,8 @@ var ReactIOSMount = {
|
||||
instance: ReactComponent,
|
||||
containerID: string
|
||||
) {
|
||||
// call back into native to remove all of the subviews from this container
|
||||
// TODO: ReactComponent.prototype.unmountComponent is missing from Flow's
|
||||
// react lib.
|
||||
(instance: any).unmountComponent();
|
||||
// Call back into native to remove all of the subviews from this container
|
||||
ReactReconciler.unmountComponent(instance);
|
||||
var containerTag =
|
||||
ReactIOSTagHandles.mostRecentMountedNodeHandleForRootNodeID(containerID);
|
||||
RCTUIManager.removeSubviewsFromContainerWithID(containerTag);
|
||||
|
||||
Reference in New Issue
Block a user