mirror of
https://github.com/status-im/react-native.git
synced 2025-02-04 05:34:15 +00:00
Support string return type from RN createReactNativeFiberComponentClass()
Reviewed By: sebmarkbage Differential Revision: D4607283 fbshipit-source-id: 466d2373dd570f77ebcced306d2f20a3f72d79c6
This commit is contained in:
parent
d7314661fb
commit
9344f3a95b
@ -540,13 +540,6 @@ const TextInput = React.createClass({
|
||||
*/
|
||||
mixins: [NativeMethodsMixin, TimerMixin],
|
||||
|
||||
viewConfig:
|
||||
((Platform.OS === 'ios' && RCTTextField ?
|
||||
RCTTextField.viewConfig :
|
||||
(Platform.OS === 'android' && AndroidTextInput ?
|
||||
AndroidTextInput.viewConfig :
|
||||
{})) : Object),
|
||||
|
||||
/**
|
||||
* Returns `true` if the input is currently focused; `false` otherwise.
|
||||
*/
|
||||
|
@ -16,6 +16,7 @@ const NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
const NativeModules = require('NativeModules');
|
||||
const Platform = require('Platform');
|
||||
const React = require('React');
|
||||
const ReactNativeFeatureFlags = require('ReactNativeFeatureFlags');
|
||||
const ReactNativeStyleAttributes = require('ReactNativeStyleAttributes');
|
||||
const ReactNativeViewAttributes = require('ReactNativeViewAttributes');
|
||||
const StyleSheetPropType = require('StyleSheetPropType');
|
||||
@ -119,6 +120,9 @@ const View = React.createClass({
|
||||
...statics,
|
||||
},
|
||||
|
||||
// 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: {
|
||||
...TVViewPropTypes,
|
||||
|
||||
@ -536,11 +540,20 @@ if (__DEV__) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO (bvaughn) Remove feature flags once all static View accessors are gone.
|
||||
// We temporarily wrap fiber native views with the create-class View above,
|
||||
// Because external code sometimes accesses static properties of this view.
|
||||
let ViewToExport = RCTView;
|
||||
if (__DEV__) {
|
||||
if (
|
||||
__DEV__ ||
|
||||
ReactNativeFeatureFlags.useFiber
|
||||
) {
|
||||
ViewToExport = View;
|
||||
} else {
|
||||
Object.assign(RCTView, statics);
|
||||
// TODO (bvaughn) Remove this mixin once all static View accessors are gone.
|
||||
Object.assign((RCTView : any), statics);
|
||||
}
|
||||
|
||||
module.exports = ViewToExport;
|
||||
// TODO (bvaughn) Temporarily mask Flow warnings for View property accesses.
|
||||
// We're wrapping the string type (Fiber) for now to avoid any actual problems.
|
||||
module.exports = ((ViewToExport : any) : typeof View);
|
||||
|
@ -26,6 +26,27 @@ invariant(UIManager, 'UIManager is undefined. The native module config is probab
|
||||
|
||||
const _takeSnapshot = UIManager.takeSnapshot;
|
||||
|
||||
// findNodeHandle() returns a reference to a wrapper component with viewConfig.
|
||||
// This wrapper is required for NativeMethodsMixin.setNativeProps, but most
|
||||
// callers want the native tag (number) and not the wrapper. For this purpose,
|
||||
// the ReactNative renderer decorates findNodeHandle() and extracts the tag.
|
||||
// However UIManager can't require ReactNative without introducing a cycle, and
|
||||
// deferring the require causes a significant performance regression in Wilde
|
||||
// (along the lines of 17% regression in RN Bridge startup). So as a temporary
|
||||
// workaround, this wrapper method mimics what the native renderer does.
|
||||
// TODO (bvaughn) Remove this and use findNodeHandle directly once stack is gone
|
||||
function findNodeHandleWrapper(componentOrHandle : any) : ?number {
|
||||
const instance: any = findNodeHandle(componentOrHandle);
|
||||
|
||||
if (instance) {
|
||||
return typeof instance._nativeTag === 'number'
|
||||
? instance._nativeTag
|
||||
: instance.getHostNode();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture an image of the screen, window or an individual view. The image
|
||||
* will be stored in a temporary file that will only exist for as long as the
|
||||
@ -57,7 +78,7 @@ UIManager.takeSnapshot = async function(
|
||||
return;
|
||||
}
|
||||
if (typeof view !== 'number' && view !== 'window') {
|
||||
view = findNodeHandle(view) || 'window';
|
||||
view = findNodeHandleWrapper(view) || 'window';
|
||||
}
|
||||
return _takeSnapshot(view, options);
|
||||
};
|
||||
|
@ -46,7 +46,7 @@ function requireNativeComponent(
|
||||
viewName: string,
|
||||
componentInterface?: ?ComponentInterface,
|
||||
extraConfig?: ?{nativeOnly?: Object},
|
||||
): Function {
|
||||
): ReactClass<any> | string {
|
||||
const viewConfig = UIManager[viewName];
|
||||
if (!viewConfig || !viewConfig.NativeProps) {
|
||||
warning(false, 'Native component for "%s" does not exist', viewName);
|
||||
|
@ -13,45 +13,25 @@
|
||||
|
||||
var ReactNative = require('ReactNative');
|
||||
var ReactNativeAttributePayload = require('ReactNativeAttributePayload');
|
||||
var ReactNativeFeatureFlags = require('ReactNativeFeatureFlags');
|
||||
var TextInputState = require('TextInputState');
|
||||
var UIManager = require('UIManager');
|
||||
|
||||
var invariant = require('fbjs/lib/invariant');
|
||||
var findNodeHandle = require('findNodeHandle');
|
||||
|
||||
type MeasureOnSuccessCallback = (
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number,
|
||||
pageX: number,
|
||||
pageY: number
|
||||
) => void
|
||||
var {
|
||||
mountSafeCallback,
|
||||
throwOnStylesProp,
|
||||
warnForStyleProps,
|
||||
} = require('NativeMethodsMixinUtils');
|
||||
|
||||
type MeasureInWindowOnSuccessCallback = (
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number,
|
||||
) => void
|
||||
|
||||
type MeasureLayoutOnSuccessCallback = (
|
||||
left: number,
|
||||
top: number,
|
||||
width: number,
|
||||
height: number
|
||||
) => void
|
||||
|
||||
function warnForStyleProps(props, validAttributes) {
|
||||
for (var key in validAttributes.style) {
|
||||
if (!(validAttributes[key] || props[key] === undefined)) {
|
||||
console.error(
|
||||
'You are setting the style `{ ' + key + ': ... }` as a prop. You ' +
|
||||
'should nest it in a style object. ' +
|
||||
'E.g. `{ style: { ' + key + ': ... } }`'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
import type {
|
||||
MeasureInWindowOnSuccessCallback,
|
||||
MeasureLayoutOnSuccessCallback,
|
||||
MeasureOnSuccessCallback,
|
||||
} from 'NativeMethodsMixinUtils';
|
||||
import type { ReactNativeBaseComponentViewConfig } from 'ReactNativeViewConfigRegistry';
|
||||
|
||||
/**
|
||||
* `NativeMethodsMixin` provides methods to access the underlying native
|
||||
@ -65,6 +45,10 @@ function warnForStyleProps(props, validAttributes) {
|
||||
* information, see [Direct
|
||||
* Manipulation](docs/direct-manipulation.html).
|
||||
*/
|
||||
// TODO (bvaughn) Figure out how to use the NativeMethodsInterface type to-
|
||||
// ensure that these mixins and ReactNativeFiberHostComponent stay in sync.
|
||||
// Unfortunately, using it causes Flow to complain WRT createClass mixins:
|
||||
// "call of method `createClass`. Expected an exact object instead of ..."
|
||||
var NativeMethodsMixin = {
|
||||
/**
|
||||
* Determines the location on screen, width, and height of the given view and
|
||||
@ -140,20 +124,15 @@ var NativeMethodsMixin = {
|
||||
* Manipulation](docs/direct-manipulation.html)).
|
||||
*/
|
||||
setNativeProps: function(nativeProps: Object) {
|
||||
if (__DEV__) {
|
||||
warnForStyleProps(nativeProps, this.viewConfig.validAttributes);
|
||||
}
|
||||
// Ensure ReactNative factory function has configured findNodeHandle.
|
||||
// Requiring it won't execute the factory function until first referenced.
|
||||
// It's possible for tests that use ReactTestRenderer to reach this point,
|
||||
// Without having executed ReactNative.
|
||||
// Defer the factory function until now to avoid a cycle with UIManager.
|
||||
// TODO (bvaughn) Remove this once ReactNativeStack is dropped.
|
||||
require('ReactNative');
|
||||
|
||||
var updatePayload = ReactNativeAttributePayload.create(
|
||||
nativeProps,
|
||||
this.viewConfig.validAttributes
|
||||
);
|
||||
|
||||
UIManager.updateView(
|
||||
(ReactNative.findNodeHandle(this) : any),
|
||||
this.viewConfig.uiViewClassName,
|
||||
updatePayload
|
||||
);
|
||||
injectedSetNativeProps(this, nativeProps);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -172,19 +151,116 @@ var NativeMethodsMixin = {
|
||||
},
|
||||
};
|
||||
|
||||
function throwOnStylesProp(component, props) {
|
||||
if (props.styles !== undefined) {
|
||||
var owner = component._owner || null;
|
||||
var name = component.constructor.displayName;
|
||||
var msg = '`styles` is not a supported property of `' + name + '`, did ' +
|
||||
'you mean `style` (singular)?';
|
||||
if (owner && owner.constructor && owner.constructor.displayName) {
|
||||
msg += '\n\nCheck the `' + owner.constructor.displayName + '` parent ' +
|
||||
' component.';
|
||||
}
|
||||
throw new Error(msg);
|
||||
// TODO (bvaughn) Inline this once ReactNativeStack is dropped.
|
||||
function setNativePropsFiber(componentOrHandle: any, nativeProps: Object) {
|
||||
// Class components don't have viewConfig -> validateAttributes.
|
||||
// Nor does it make sense to set native props on a non-native component.
|
||||
// Instead, find the nearest host component and set props on it.
|
||||
// Use findNodeHandle() rather than ReactNative.findNodeHandle() because
|
||||
// We want the instance/wrapper (not the native tag).
|
||||
let maybeInstance;
|
||||
|
||||
// Fiber errors if findNodeHandle is called for an umounted component.
|
||||
// Tests using ReactTestRenderer will trigger this case indirectly.
|
||||
// Mimicking stack behavior, we should silently ignore this case.
|
||||
// TODO Fix ReactTestRenderer so we can remove this try/catch.
|
||||
try {
|
||||
maybeInstance = findNodeHandle(componentOrHandle);
|
||||
} catch (error) {}
|
||||
|
||||
// If there is no host component beneath this we should fail silently.
|
||||
// This is not an error; it could mean a class component rendered null.
|
||||
if (maybeInstance == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const viewConfig : ReactNativeBaseComponentViewConfig =
|
||||
maybeInstance.viewConfig;
|
||||
|
||||
if (__DEV__) {
|
||||
warnForStyleProps(nativeProps, viewConfig.validAttributes);
|
||||
}
|
||||
|
||||
var updatePayload = ReactNativeAttributePayload.create(
|
||||
nativeProps,
|
||||
viewConfig.validAttributes,
|
||||
);
|
||||
|
||||
UIManager.updateView(
|
||||
maybeInstance._nativeTag,
|
||||
viewConfig.uiViewClassName,
|
||||
updatePayload,
|
||||
);
|
||||
}
|
||||
|
||||
// TODO (bvaughn) Remove this once ReactNativeStack is dropped.
|
||||
function setNativePropsStack(componentOrHandle: any, nativeProps: Object) {
|
||||
// Class components don't have viewConfig -> validateAttributes.
|
||||
// Nor does it make sense to set native props on a non-native component.
|
||||
// Instead, find the nearest host component and set props on it.
|
||||
// Use findNodeHandle() rather than ReactNative.findNodeHandle() because
|
||||
// We want the instance/wrapper (not the native tag).
|
||||
let maybeInstance = findNodeHandle(componentOrHandle);
|
||||
|
||||
// If there is no host component beneath this we should fail silently.
|
||||
// This is not an error; it could mean a class component rendered null.
|
||||
if (maybeInstance == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let viewConfig : ReactNativeBaseComponentViewConfig;
|
||||
if (maybeInstance.viewConfig !== undefined) {
|
||||
// ReactNativeBaseComponent
|
||||
viewConfig = maybeInstance.viewConfig;
|
||||
} else if (
|
||||
maybeInstance._instance !== undefined &&
|
||||
maybeInstance._instance.viewConfig !== undefined
|
||||
) {
|
||||
// ReactCompositeComponentWrapper
|
||||
// Some instances (eg Text) define their own viewConfig
|
||||
viewConfig = maybeInstance._instance.viewConfig;
|
||||
} else {
|
||||
// ReactCompositeComponentWrapper
|
||||
// Other instances (eg TextInput) defer to their children's viewConfig
|
||||
while (maybeInstance._renderedComponent !== undefined) {
|
||||
maybeInstance = maybeInstance._renderedComponent;
|
||||
}
|
||||
viewConfig = maybeInstance.viewConfig;
|
||||
}
|
||||
|
||||
const tag : number = typeof maybeInstance.getHostNode === 'function'
|
||||
? maybeInstance.getHostNode()
|
||||
: maybeInstance._rootNodeID;
|
||||
|
||||
if (__DEV__) {
|
||||
warnForStyleProps(nativeProps, viewConfig.validAttributes);
|
||||
}
|
||||
|
||||
var updatePayload = ReactNativeAttributePayload.create(
|
||||
nativeProps,
|
||||
viewConfig.validAttributes,
|
||||
);
|
||||
|
||||
UIManager.updateView(
|
||||
tag,
|
||||
viewConfig.uiViewClassName,
|
||||
updatePayload,
|
||||
);
|
||||
}
|
||||
|
||||
// Switching based on fiber vs stack to avoid a lot of inline checks at runtime.
|
||||
// HACK Normally this injection would be done by the renderer, but in this case
|
||||
// that would result in a cycle between ReactNative and NativeMethodsMixin.
|
||||
// We avoid requiring additional code for this injection so it's probably ok?
|
||||
// TODO (bvaughn) Remove this once ReactNativeStack is gone.
|
||||
let injectedSetNativeProps :
|
||||
(componentOrHandle: any, nativeProps: Object) => void;
|
||||
if (ReactNativeFeatureFlags.useFiber) {
|
||||
injectedSetNativeProps = setNativePropsFiber;
|
||||
} else {
|
||||
injectedSetNativeProps = setNativePropsStack;
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
// hide this from Flow since we can't define these properties outside of
|
||||
// __DEV__ without actually implementing them (setting them to undefined
|
||||
@ -203,20 +279,4 @@ if (__DEV__) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* In the future, we should cleanup callbacks by cancelling them instead of
|
||||
* using this.
|
||||
*/
|
||||
function mountSafeCallback(
|
||||
context: ReactComponent<any, any, any>,
|
||||
callback: ?Function
|
||||
): any {
|
||||
return function() {
|
||||
if (!callback || (typeof context.isMounted === 'function' && !context.isMounted())) {
|
||||
return undefined;
|
||||
}
|
||||
return callback.apply(context, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = NativeMethodsMixin;
|
||||
|
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* 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 NativeMethodsMixinUtils
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
export type MeasureOnSuccessCallback = (
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number,
|
||||
pageX: number,
|
||||
pageY: number
|
||||
) => void
|
||||
|
||||
export type MeasureInWindowOnSuccessCallback = (
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number,
|
||||
) => void
|
||||
|
||||
export type MeasureLayoutOnSuccessCallback = (
|
||||
left: number,
|
||||
top: number,
|
||||
width: number,
|
||||
height: number
|
||||
) => void
|
||||
|
||||
/**
|
||||
* Shared between ReactNativeFiberHostComponent and NativeMethodsMixin to keep
|
||||
* API in sync.
|
||||
*/
|
||||
export interface NativeMethodsInterface {
|
||||
blur() : void,
|
||||
focus() : void,
|
||||
measure(callback : MeasureOnSuccessCallback) : void,
|
||||
measureInWindow(callback : MeasureInWindowOnSuccessCallback) : void,
|
||||
measureLayout(
|
||||
relativeToNativeNode: number,
|
||||
onSuccess: MeasureLayoutOnSuccessCallback,
|
||||
onFail: () => void /* currently unused */
|
||||
) : void,
|
||||
setNativeProps(nativeProps: Object) : void,
|
||||
}
|
||||
|
||||
/**
|
||||
* In the future, we should cleanup callbacks by cancelling them instead of
|
||||
* using this.
|
||||
*/
|
||||
function mountSafeCallback(
|
||||
context: any,
|
||||
callback: ?Function
|
||||
): any {
|
||||
return function() {
|
||||
if (!callback || (typeof context.isMounted === 'function' && !context.isMounted())) {
|
||||
return undefined;
|
||||
}
|
||||
return callback.apply(context, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
function throwOnStylesProp(component : any, props : any) {
|
||||
if (props.styles !== undefined) {
|
||||
var owner = component._owner || null;
|
||||
var name = component.constructor.displayName;
|
||||
var msg = '`styles` is not a supported property of `' + name + '`, did ' +
|
||||
'you mean `style` (singular)?';
|
||||
if (owner && owner.constructor && owner.constructor.displayName) {
|
||||
msg += '\n\nCheck the `' + owner.constructor.displayName + '` parent ' +
|
||||
' component.';
|
||||
}
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function warnForStyleProps(props : any, validAttributes : any) {
|
||||
for (var key in validAttributes.style) {
|
||||
if (!(validAttributes[key] || props[key] === undefined)) {
|
||||
console.error(
|
||||
'You are setting the style `{ ' + key + ': ... }` as a prop. You ' +
|
||||
'should nest it in a style object. ' +
|
||||
'E.g. `{ style: { ' + key + ': ... } }`'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
mountSafeCallback,
|
||||
throwOnStylesProp,
|
||||
warnForStyleProps,
|
||||
};
|
@ -15,4 +15,4 @@ const ReactNativeFeatureFlags = require('ReactNativeFeatureFlags');
|
||||
|
||||
module.exports = ReactNativeFeatureFlags.useFiber
|
||||
? require('ReactNativeFiber')
|
||||
: require('ReactNativeStack')
|
||||
: require('ReactNativeStack');
|
||||
|
@ -12,16 +12,11 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import type { Element } from 'React';
|
||||
import type { Fiber } from 'ReactFiber';
|
||||
import type { ReactNodeList } from 'ReactTypes';
|
||||
import type { ReactNativeBaseComponentViewConfig } from 'ReactNativeViewConfigRegistry';
|
||||
|
||||
const NativeMethodsMixin = require('NativeMethodsMixin');
|
||||
const ReactFiberReconciler = require('ReactFiberReconciler');
|
||||
const ReactGenericBatching = require('ReactGenericBatching');
|
||||
const ReactNativeAttributePayload = require('ReactNativeAttributePayload');
|
||||
const ReactNativeComponentTree = require('ReactNativeComponentTree');
|
||||
const ReactNativeFiberHostComponent = require('ReactNativeFiberHostComponent');
|
||||
const ReactNativeInjection = require('ReactNativeInjection');
|
||||
const ReactNativeTagHandles = require('ReactNativeTagHandles');
|
||||
const ReactNativeViewConfigRegistry = require('ReactNativeViewConfigRegistry');
|
||||
@ -34,6 +29,11 @@ const findNodeHandle = require('findNodeHandle');
|
||||
const invariant = require('fbjs/lib/invariant');
|
||||
|
||||
const { injectInternals } = require('ReactFiberDevToolsHook');
|
||||
|
||||
import type { Element } from 'React';
|
||||
import type { Fiber } from 'ReactFiber';
|
||||
import type { ReactNativeBaseComponentViewConfig } from 'ReactNativeViewConfigRegistry';
|
||||
import type { ReactNodeList } from 'ReactTypes';
|
||||
const {
|
||||
precacheFiberNode,
|
||||
uncacheFiberNode,
|
||||
@ -43,7 +43,7 @@ const {
|
||||
ReactNativeInjection.inject();
|
||||
|
||||
type Container = number;
|
||||
type Instance = {
|
||||
export type Instance = {
|
||||
_children: Array<Instance | number>,
|
||||
_nativeTag: number,
|
||||
viewConfig: ReactNativeBaseComponentViewConfig,
|
||||
@ -51,13 +51,6 @@ type Instance = {
|
||||
type Props = Object;
|
||||
type TextInstance = number;
|
||||
|
||||
function NativeHostComponent(tag, viewConfig) {
|
||||
this._nativeTag = tag;
|
||||
this._children = [];
|
||||
this.viewConfig = viewConfig;
|
||||
}
|
||||
Object.assign(NativeHostComponent.prototype, NativeMethodsMixin);
|
||||
|
||||
function recursivelyUncacheFiberNode(node : Instance | TextInstance) {
|
||||
if (typeof node === 'number') { // Leaf node (eg text)
|
||||
uncacheFiberNode(node);
|
||||
@ -156,7 +149,7 @@ const NativeRenderer = ReactFiberReconciler({
|
||||
const viewConfig = ReactNativeViewConfigRegistry.get(type);
|
||||
|
||||
if (__DEV__) {
|
||||
for (let key in viewConfig.validAttributes) {
|
||||
for (const key in viewConfig.validAttributes) {
|
||||
if (props.hasOwnProperty(key)) {
|
||||
deepFreezeAndThrowOnMutationInDev(props[key]);
|
||||
}
|
||||
@ -175,12 +168,14 @@ const NativeRenderer = ReactFiberReconciler({
|
||||
updatePayload, // props
|
||||
);
|
||||
|
||||
const component = new NativeHostComponent(tag, viewConfig);
|
||||
const component = new ReactNativeFiberHostComponent(tag, viewConfig);
|
||||
|
||||
precacheFiberNode(internalInstanceHandle, tag);
|
||||
updateFiberProps(tag, props);
|
||||
|
||||
return component;
|
||||
// Not sure how to avoid this cast. Flow is okay if the component is defined
|
||||
// in the same file but if it's external it can't see the types.
|
||||
return ((component : any) : Instance);
|
||||
},
|
||||
|
||||
createTextInstance(
|
||||
@ -367,17 +362,20 @@ ReactGenericBatching.injection.injectFiberBatchedUpdates(
|
||||
const roots = new Map();
|
||||
|
||||
findNodeHandle.injection.injectFindNode(
|
||||
(fiber: Fiber) => {
|
||||
const instance: any = NativeRenderer.findHostInstance(fiber);
|
||||
return instance ? instance._nativeTag : null;
|
||||
}
|
||||
(fiber: Fiber) => NativeRenderer.findHostInstance(fiber)
|
||||
);
|
||||
findNodeHandle.injection.injectFindRootNodeID(
|
||||
(instance) => instance._nativeTag
|
||||
(instance) => instance
|
||||
);
|
||||
|
||||
const ReactNative = {
|
||||
findNodeHandle,
|
||||
// External users of findNodeHandle() expect the host tag number return type.
|
||||
// The injected findNodeHandle() strategy returns the instance wrapper though.
|
||||
// See NativeMethodsMixin#setNativeProps for more info on why this is done.
|
||||
findNodeHandle(componentOrHandle : any) : ?number {
|
||||
const instance: any = findNodeHandle(componentOrHandle);
|
||||
return instance ? instance._nativeTag : null;
|
||||
},
|
||||
|
||||
render(element : Element<any>, containerTag : any, callback: ?Function) {
|
||||
let root = roots.get(containerTag);
|
||||
|
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Copyright 2013-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 ReactNativeFiberHostComponent
|
||||
* @flow
|
||||
* @preventMunge
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var ReactNativeAttributePayload = require('ReactNativeAttributePayload');
|
||||
var TextInputState = require('TextInputState');
|
||||
var UIManager = require('UIManager');
|
||||
|
||||
var {
|
||||
mountSafeCallback,
|
||||
warnForStyleProps,
|
||||
} = require('NativeMethodsMixinUtils');
|
||||
|
||||
import type {
|
||||
MeasureInWindowOnSuccessCallback,
|
||||
MeasureLayoutOnSuccessCallback,
|
||||
MeasureOnSuccessCallback,
|
||||
NativeMethodsInterface,
|
||||
} from 'NativeMethodsMixinUtils';
|
||||
import type { Instance } from 'ReactNativeFiber';
|
||||
import type { ReactNativeBaseComponentViewConfig } from 'ReactNativeViewConfigRegistry';
|
||||
|
||||
/**
|
||||
* This component defines the same methods as NativeMethodsMixin but without the
|
||||
* findNodeHandle wrapper. This wrapper is unnecessary for HostComponent views
|
||||
* and would also result in a circular require.js dependency (since
|
||||
* ReactNativeFiber depends on this component and NativeMethodsMixin depends on
|
||||
* ReactNativeFiber).
|
||||
*/
|
||||
class ReactNativeFiberHostComponent implements NativeMethodsInterface {
|
||||
_children: Array<Instance | number>
|
||||
_nativeTag: number
|
||||
viewConfig: ReactNativeBaseComponentViewConfig
|
||||
|
||||
constructor(
|
||||
tag : number,
|
||||
viewConfig : ReactNativeBaseComponentViewConfig
|
||||
) {
|
||||
this._nativeTag = tag;
|
||||
this._children = [];
|
||||
this.viewConfig = viewConfig;
|
||||
}
|
||||
|
||||
blur() {
|
||||
TextInputState.blurTextInput(this._nativeTag);
|
||||
}
|
||||
|
||||
focus() {
|
||||
TextInputState.focusTextInput(this._nativeTag);
|
||||
}
|
||||
|
||||
measure(callback: MeasureOnSuccessCallback) {
|
||||
UIManager.measure(
|
||||
this._nativeTag,
|
||||
mountSafeCallback(this, callback)
|
||||
);
|
||||
}
|
||||
|
||||
measureInWindow(callback: MeasureInWindowOnSuccessCallback) {
|
||||
UIManager.measureInWindow(
|
||||
this._nativeTag,
|
||||
mountSafeCallback(this, callback)
|
||||
);
|
||||
}
|
||||
|
||||
measureLayout(
|
||||
relativeToNativeNode: number,
|
||||
onSuccess: MeasureLayoutOnSuccessCallback,
|
||||
onFail: () => void /* currently unused */
|
||||
) {
|
||||
UIManager.measureLayout(
|
||||
this._nativeTag,
|
||||
relativeToNativeNode,
|
||||
mountSafeCallback(this, onFail),
|
||||
mountSafeCallback(this, onSuccess)
|
||||
);
|
||||
}
|
||||
|
||||
setNativeProps(nativeProps: Object) {
|
||||
if (__DEV__) {
|
||||
warnForStyleProps(nativeProps, this.viewConfig.validAttributes);
|
||||
}
|
||||
|
||||
var updatePayload = ReactNativeAttributePayload.create(
|
||||
nativeProps,
|
||||
this.viewConfig.validAttributes
|
||||
);
|
||||
|
||||
UIManager.updateView(
|
||||
this._nativeTag,
|
||||
this.viewConfig.uiViewClassName,
|
||||
updatePayload
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ReactNativeFiberHostComponent;
|
@ -13,8 +13,8 @@
|
||||
|
||||
var ReactNativeComponentTree = require('ReactNativeComponentTree');
|
||||
var ReactNativeInjection = require('ReactNativeInjection');
|
||||
var ReactNativeStackInjection = require('ReactNativeStackInjection');
|
||||
var ReactNativeMount = require('ReactNativeMount');
|
||||
var ReactNativeStackInjection = require('ReactNativeStackInjection');
|
||||
var ReactUpdates = require('ReactUpdates');
|
||||
|
||||
var findNodeHandle = require('findNodeHandle');
|
||||
@ -30,16 +30,16 @@ var render = function(
|
||||
return ReactNativeMount.renderComponent(element, mountInto, callback);
|
||||
};
|
||||
|
||||
findNodeHandle.injection.injectFindNode(
|
||||
(instance) => instance.getHostNode()
|
||||
);
|
||||
findNodeHandle.injection.injectFindRootNodeID(
|
||||
(instance) => instance._rootNodeID
|
||||
);
|
||||
|
||||
var ReactNative = {
|
||||
hasReactNativeInitialized: false,
|
||||
findNodeHandle: findNodeHandle,
|
||||
|
||||
// External users of findNodeHandle() expect the host tag number return type.
|
||||
// The injected findNodeHandle() strategy returns the instance wrapper though.
|
||||
// See NativeMethodsMixin#setNativeProps for more info on why this is done.
|
||||
findNodeHandle(componentOrHandle : any) : ?number {
|
||||
return findNodeHandle(componentOrHandle).getHostNode();
|
||||
},
|
||||
|
||||
render: render,
|
||||
unmountComponentAtNode: ReactNativeMount.unmountComponentAtNode,
|
||||
|
||||
|
@ -63,10 +63,10 @@ function inject() {
|
||||
};
|
||||
|
||||
findNodeHandle.injection.injectFindNode(
|
||||
(instance) => instance.getHostNode()
|
||||
(instance) => instance
|
||||
);
|
||||
findNodeHandle.injection.injectFindRootNodeID(
|
||||
(instance) => instance._rootNodeID
|
||||
(instance) => instance
|
||||
);
|
||||
|
||||
ReactEmptyComponent.injection.injectEmptyComponentFactory(EmptyComponent);
|
||||
|
@ -13,8 +13,8 @@
|
||||
'use strict';
|
||||
|
||||
const ReactNativeBaseComponent = require('ReactNativeBaseComponent');
|
||||
const ReactNativeViewConfigRegistry = require('ReactNativeViewConfigRegistry');
|
||||
const ReactNativeFeatureFlags = require('ReactNativeFeatureFlags');
|
||||
const ReactNativeViewConfigRegistry = require('ReactNativeViewConfigRegistry');
|
||||
|
||||
// See also ReactNativeBaseComponent
|
||||
type ReactNativeBaseComponentViewConfig = {
|
||||
@ -27,14 +27,12 @@ type ReactNativeBaseComponentViewConfig = {
|
||||
* @param {string} config iOS View configuration.
|
||||
* @private
|
||||
*/
|
||||
const createReactNativeFiberComponentClass = function(
|
||||
viewConfig: ReactNativeBaseComponentViewConfig
|
||||
): ReactClass<any> {
|
||||
// TODO(sema): This actually returns a string. Need to fix this before
|
||||
// we deploy Fiber.
|
||||
return (ReactNativeViewConfigRegistry.register(viewConfig) : any);
|
||||
};
|
||||
|
||||
const createReactNativeFiberComponentClass = function(
|
||||
viewConfig: ReactNativeBaseComponentViewConfig
|
||||
): string {
|
||||
return ReactNativeViewConfigRegistry.register(viewConfig);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} config iOS View configuration.
|
||||
* @private
|
||||
|
@ -53,7 +53,10 @@ import type { ReactInstance } from 'ReactInstanceType';
|
||||
let injectedFindNode;
|
||||
let injectedFindRootNodeID;
|
||||
|
||||
function findNodeHandle(componentOrHandle: any): ?number {
|
||||
// TODO (bvaughn) Rename the findNodeHandle module to something more descriptive
|
||||
// eg findInternalHostInstance. This will reduce the likelihood of someone
|
||||
// accidentally deep-requiring this version.
|
||||
function findNodeHandle(componentOrHandle: any): any {
|
||||
if (__DEV__) {
|
||||
// TODO: fix this unsafe cast to work with Fiber.
|
||||
var owner = ((ReactCurrentOwner.current: any): ReactInstance | null);
|
||||
|
Loading…
x
Reference in New Issue
Block a user