[Native] Delete NativeComponent and NativeMethodsMixin (#18036)

* [Native] Delete NativeComponent and NativeMethodsMixin

* Remove more files
This commit is contained in:
Eli White
2020-02-13 15:09:25 -08:00
committed by GitHub
parent a4376e064d
commit b2c103652d
10 changed files with 259 additions and 1256 deletions
-330
View File
@@ -1,330 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
import type {
MeasureInWindowOnSuccessCallback,
MeasureLayoutOnSuccessCallback,
MeasureOnSuccessCallback,
NativeMethodsMixinType,
ReactNativeBaseComponentViewConfig,
} from './ReactNativeTypes';
import invariant from 'shared/invariant';
// Modules provided by RN:
import {
TextInputState,
UIManager,
} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
import {create} from './ReactNativeAttributePayload';
import {
mountSafeCallback_NOT_REALLY_SAFE,
throwOnStylesProp,
warnForStyleProps,
} from './NativeMethodsMixinUtils';
export default function(
findNodeHandle: any => ?number,
findHostInstance: any => any,
) {
/**
* `NativeMethodsMixin` provides methods to access the underlying native
* component directly. This can be useful in cases when you want to focus
* a view or measure its on-screen dimensions, for example.
*
* The methods described here are available on most of the default components
* provided by React Native. Note, however, that they are *not* available on
* composite components that aren't directly backed by a native view. This will
* generally include most components that you define in your own app. For more
* information, see [Direct
* Manipulation](docs/direct-manipulation.html).
*
* Note the Flow $Exact<> syntax is required to support mixins.
* React createClass mixins can only be used with exact types.
*/
const NativeMethodsMixin: $Exact<NativeMethodsMixinType> = {
/**
* Determines the location on screen, width, and height of the given view and
* returns the values via an async callback. If successful, the callback will
* be called with the following arguments:
*
* - x
* - y
* - width
* - height
* - pageX
* - pageY
*
* Note that these measurements are not available until after the rendering
* has been completed in native. If you need the measurements as soon as
* possible, consider using the [`onLayout`
* prop](docs/view.html#onlayout) instead.
*/
measure: function(callback: MeasureOnSuccessCallback) {
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 = findHostInstance(this);
} 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;
}
if (maybeInstance.canonical) {
// We can't call FabricUIManager here because it won't be loaded in paper
// at initialization time. See https://github.com/facebook/react/pull/15490
// for more info.
nativeFabricUIManager.measure(
maybeInstance.node,
mountSafeCallback_NOT_REALLY_SAFE(this, callback),
);
} else {
UIManager.measure(
findNodeHandle(this),
mountSafeCallback_NOT_REALLY_SAFE(this, callback),
);
}
},
/**
* Determines the location of the given view in the window and returns the
* values via an async callback. If the React root view is embedded in
* another native view, this will give you the absolute coordinates. If
* successful, the callback will be called with the following
* arguments:
*
* - x
* - y
* - width
* - height
*
* Note that these measurements are not available until after the rendering
* has been completed in native.
*/
measureInWindow: function(callback: MeasureInWindowOnSuccessCallback) {
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 = findHostInstance(this);
} 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;
}
if (maybeInstance.canonical) {
// We can't call FabricUIManager here because it won't be loaded in paper
// at initialization time. See https://github.com/facebook/react/pull/15490
// for more info.
nativeFabricUIManager.measureInWindow(
maybeInstance.node,
mountSafeCallback_NOT_REALLY_SAFE(this, callback),
);
} else {
UIManager.measureInWindow(
findNodeHandle(this),
mountSafeCallback_NOT_REALLY_SAFE(this, callback),
);
}
},
/**
* Like [`measure()`](#measure), but measures the view relative an ancestor,
* specified as `relativeToNativeNode`. This means that the returned x, y
* are relative to the origin x, y of the ancestor view.
*
* As always, to obtain a native node handle for a component, you can use
* `findNodeHandle(component)`.
*/
measureLayout: function(
relativeToNativeNode: number | Object,
onSuccess: MeasureLayoutOnSuccessCallback,
onFail?: () => void /* currently unused */,
) {
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 = findHostInstance(this);
} 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;
}
if (maybeInstance.canonical) {
if (__DEV__) {
console.error(
'Warning: measureLayout on components using NativeMethodsMixin ' +
'or ReactNative.NativeComponent is not currently supported in Fabric. ' +
'measureLayout must be called on a native ref. Consider using forwardRef.',
);
}
return;
} else {
let relativeNode;
if (typeof relativeToNativeNode === 'number') {
// Already a node handle
relativeNode = relativeToNativeNode;
} else if (relativeToNativeNode._nativeTag) {
relativeNode = relativeToNativeNode._nativeTag;
}
if (relativeNode == null) {
if (__DEV__) {
console.error(
'Warning: ref.measureLayout must be called with a node handle or a ref to a native component.',
);
}
return;
}
UIManager.measureLayout(
findNodeHandle(this),
relativeNode,
mountSafeCallback_NOT_REALLY_SAFE(this, onFail),
mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess),
);
}
},
/**
* This function sends props straight to native. They will not participate in
* future diff process - this means that if you do not include them in the
* next render, they will remain active (see [Direct
* Manipulation](docs/direct-manipulation.html)).
*/
setNativeProps: function(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 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 = findHostInstance(this);
} 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;
}
if (maybeInstance.canonical) {
if (__DEV__) {
console.error(
'Warning: setNativeProps is not currently supported in Fabric',
);
}
return;
}
const nativeTag =
maybeInstance._nativeTag || maybeInstance.canonical._nativeTag;
const viewConfig: ReactNativeBaseComponentViewConfig<> =
maybeInstance.viewConfig || maybeInstance.canonical.viewConfig;
if (__DEV__) {
warnForStyleProps(nativeProps, viewConfig.validAttributes);
}
const updatePayload = create(nativeProps, viewConfig.validAttributes);
// Avoid the overhead of bridge calls if there's no update.
// This is an expensive no-op for Android, and causes an unnecessary
// view invalidation for certain components (eg RCTTextInput) on iOS.
if (updatePayload != null) {
UIManager.updateView(
nativeTag,
viewConfig.uiViewClassName,
updatePayload,
);
}
},
/**
* Requests focus for the given input or view. The exact behavior triggered
* will depend on the platform and type of view.
*/
focus: function() {
TextInputState.focusTextInput(findNodeHandle(this));
},
/**
* Removes focus from an input or view. This is the opposite of `focus()`.
*/
blur: function() {
TextInputState.blurTextInput(findNodeHandle(this));
},
};
if (__DEV__) {
// hide this from Flow since we can't define these properties outside of
// __DEV__ without actually implementing them (setting them to undefined
// isn't allowed by ReactClass)
const NativeMethodsMixin_DEV = (NativeMethodsMixin: any);
invariant(
!NativeMethodsMixin_DEV.componentWillMount &&
!NativeMethodsMixin_DEV.componentWillReceiveProps &&
!NativeMethodsMixin_DEV.UNSAFE_componentWillMount &&
!NativeMethodsMixin_DEV.UNSAFE_componentWillReceiveProps,
'Do not override existing functions.',
);
// TODO (bvaughn) Remove cWM and cWRP in a future version of React Native,
// Once these lifecycles have been remove from the reconciler.
NativeMethodsMixin_DEV.componentWillMount = function() {
throwOnStylesProp(this, this.props);
};
NativeMethodsMixin_DEV.componentWillReceiveProps = function(newProps) {
throwOnStylesProp(this, newProps);
};
NativeMethodsMixin_DEV.UNSAFE_componentWillMount = function() {
throwOnStylesProp(this, this.props);
};
NativeMethodsMixin_DEV.UNSAFE_componentWillReceiveProps = function(
newProps,
) {
throwOnStylesProp(this, newProps);
};
// React may warn about cWM/cWRP/cWU methods being deprecated.
// Add a flag to suppress these warnings for this special case.
// TODO (bvaughn) Remove this flag once the above methods have been removed.
NativeMethodsMixin_DEV.componentWillMount.__suppressDeprecationWarning = true;
NativeMethodsMixin_DEV.componentWillReceiveProps.__suppressDeprecationWarning = true;
}
return NativeMethodsMixin;
}
+1 -8
View File
@@ -32,8 +32,6 @@ import ReactVersion from 'shared/ReactVersion';
// Module provided by RN:
import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
import NativeMethodsMixin from './NativeMethodsMixin';
import ReactNativeComponent from './ReactNativeComponent';
import {getClosestInstanceFromNode} from './ReactFabricComponentTree';
import {getInspectorDataForViewTag} from './ReactNativeFiberInspector';
@@ -155,8 +153,6 @@ setBatchingImplementation(
const roots = new Map();
const ReactFabric: ReactFabricType = {
NativeComponent: ReactNativeComponent(findNodeHandle, findHostInstance),
// This is needed for implementation details of TouchableNativeFeedback
// Remove this once TouchableNativeFeedback doesn't use cloneElement
findHostInstance_DEPRECATED,
@@ -223,10 +219,7 @@ const ReactFabric: ReactFabricType = {
return createPortal(children, containerTag, null, key);
},
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
// Used as a mixin in many createClass-based components
NativeMethodsMixin: NativeMethodsMixin(findNodeHandle, findHostInstance),
},
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {},
};
injectIntoDevTools({
@@ -1,285 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
*/
import type {
MeasureInWindowOnSuccessCallback,
MeasureLayoutOnSuccessCallback,
MeasureOnSuccessCallback,
NativeMethods,
ReactNativeBaseComponentViewConfig,
} from './ReactNativeTypes';
import React from 'react';
// Modules provided by RN:
import {
TextInputState,
UIManager,
} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
import {create} from './ReactNativeAttributePayload';
import {mountSafeCallback_NOT_REALLY_SAFE} from './NativeMethodsMixinUtils';
export default function(
findNodeHandle: any => ?number,
findHostInstance: any => any,
) {
/**
* Superclass that provides methods to access the underlying native component.
* This can be useful when you want to focus a view or measure its dimensions.
*
* Methods implemented by this class are available on most default components
* provided by React Native. However, they are *not* available on composite
* components that are not directly backed by a native view. For more
* information, see [Direct Manipulation](docs/direct-manipulation.html).
*
* @abstract
*/
class ReactNativeComponent<Props> extends React.Component<Props> {
/**
* Due to bugs in Flow's handling of React.createClass, some fields already
* declared in the base class need to be redeclared below.
*/
props: Props;
/**
* Removes focus. This is the opposite of `focus()`.
*/
blur(): void {
TextInputState.blurTextInput(findNodeHandle(this));
}
/**
* Requests focus. The exact behavior depends on the platform and view.
*/
focus(): void {
TextInputState.focusTextInput(findNodeHandle(this));
}
/**
* Measures the on-screen location and dimensions. If successful, the callback
* will be called asynchronously with the following arguments:
*
* - x
* - y
* - width
* - height
* - pageX
* - pageY
*
* These values are not available until after natives rendering completes. If
* you need the measurements as soon as possible, consider using the
* [`onLayout` prop](docs/view.html#onlayout) instead.
*/
measure(callback: MeasureOnSuccessCallback): void {
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 = findHostInstance(this);
} 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;
}
if (maybeInstance.canonical) {
// We can't call FabricUIManager here because it won't be loaded in paper
// at initialization time. See https://github.com/facebook/react/pull/15490
// for more info.
nativeFabricUIManager.measure(
maybeInstance.node,
mountSafeCallback_NOT_REALLY_SAFE(this, callback),
);
} else {
UIManager.measure(
findNodeHandle(this),
mountSafeCallback_NOT_REALLY_SAFE(this, callback),
);
}
}
/**
* Measures the on-screen location and dimensions. Even if the React Native
* root view is embedded within another native view, this method will give you
* the absolute coordinates measured from the window. If successful, the
* callback will be called asynchronously with the following arguments:
*
* - x
* - y
* - width
* - height
*
* These values are not available until after natives rendering completes.
*/
measureInWindow(callback: MeasureInWindowOnSuccessCallback): void {
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 = findHostInstance(this);
} 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;
}
if (maybeInstance.canonical) {
// We can't call FabricUIManager here because it won't be loaded in paper
// at initialization time. See https://github.com/facebook/react/pull/15490
// for more info.
nativeFabricUIManager.measureInWindow(
maybeInstance.node,
mountSafeCallback_NOT_REALLY_SAFE(this, callback),
);
} else {
UIManager.measureInWindow(
findNodeHandle(this),
mountSafeCallback_NOT_REALLY_SAFE(this, callback),
);
}
}
/**
* Similar to [`measure()`](#measure), but the resulting location will be
* relative to the supplied ancestor's location.
*
* Obtain a native node handle with `ReactNative.findNodeHandle(component)`.
*/
measureLayout(
relativeToNativeNode: number | Object,
onSuccess: MeasureLayoutOnSuccessCallback,
onFail?: () => void /* currently unused */,
): void {
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 = findHostInstance(this);
} 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;
}
if (maybeInstance.canonical) {
if (__DEV__) {
console.error(
'Warning: measureLayout on components using NativeMethodsMixin ' +
'or ReactNative.NativeComponent is not currently supported in Fabric. ' +
'measureLayout must be called on a native ref. Consider using forwardRef.',
);
}
return;
} else {
let relativeNode;
if (typeof relativeToNativeNode === 'number') {
// Already a node handle
relativeNode = relativeToNativeNode;
} else if (relativeToNativeNode._nativeTag) {
relativeNode = relativeToNativeNode._nativeTag;
}
if (relativeNode == null) {
if (__DEV__) {
console.error(
'Warning: ref.measureLayout must be called with a node handle or a ref to a native component.',
);
}
return;
}
UIManager.measureLayout(
findNodeHandle(this),
relativeNode,
mountSafeCallback_NOT_REALLY_SAFE(this, onFail),
mountSafeCallback_NOT_REALLY_SAFE(this, onSuccess),
);
}
}
/**
* This function sends props straight to native. They will not participate in
* future diff process - this means that if you do not include them in the
* next render, they will remain active (see [Direct
* Manipulation](docs/direct-manipulation.html)).
*/
setNativeProps(nativeProps: Object): void {
// 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 = findHostInstance(this);
} 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;
}
if (maybeInstance.canonical) {
if (__DEV__) {
console.error(
'Warning: setNativeProps is not currently supported in Fabric',
);
}
return;
}
const nativeTag =
maybeInstance._nativeTag || maybeInstance.canonical._nativeTag;
const viewConfig: ReactNativeBaseComponentViewConfig<> =
maybeInstance.viewConfig || maybeInstance.canonical.viewConfig;
const updatePayload = create(nativeProps, viewConfig.validAttributes);
// Avoid the overhead of bridge calls if there's no update.
// This is an expensive no-op for Android, and causes an unnecessary
// view invalidation for certain components (eg RCTTextInput) on iOS.
if (updatePayload != null) {
UIManager.updateView(
nativeTag,
viewConfig.uiViewClassName,
updatePayload,
);
}
}
}
// eslint-disable-next-line no-unused-expressions
(ReactNativeComponent.prototype: NativeMethods);
return ReactNativeComponent;
}
@@ -28,13 +28,6 @@ import {
warnForStyleProps,
} from './NativeMethodsMixinUtils';
/**
* 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 {
_children: Array<Instance | number>;
_nativeTag: number;
@@ -35,8 +35,6 @@ import ReactVersion from 'shared/ReactVersion';
// Module provided by RN:
import {UIManager} from 'react-native/Libraries/ReactPrivate/ReactNativePrivateInterface';
import NativeMethodsMixin from './NativeMethodsMixin';
import ReactNativeComponent from './ReactNativeComponent';
import {getClosestInstanceFromNode} from './ReactNativeComponentTree';
import {getInspectorDataForViewTag} from './ReactNativeFiberInspector';
@@ -164,8 +162,6 @@ function computeComponentStackForErrorReporting(reactTag: number): string {
const roots = new Map();
const ReactNativeRenderer: ReactNativeType = {
NativeComponent: ReactNativeComponent(findNodeHandle, findHostInstance),
// This is needed for implementation details of TouchableNativeFeedback
// Remove this once TouchableNativeFeedback doesn't use cloneElement
findHostInstance_DEPRECATED,
@@ -235,8 +231,6 @@ const ReactNativeRenderer: ReactNativeType = {
unstable_batchedUpdates: batchedUpdates,
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
// Used as a mixin in many createClass-based components
NativeMethodsMixin: NativeMethodsMixin(findNodeHandle, findHostInstance),
computeComponentStackForErrorReporting,
},
};
+2 -34
View File
@@ -8,7 +8,7 @@
* @flow
*/
import React, {type ElementRef, type AbstractComponent} from 'react';
import type {ElementRef, AbstractComponent} from 'react';
export type MeasureOnSuccessCallback = (
x: number,
@@ -77,31 +77,6 @@ export type ReactNativeBaseComponentViewConfig<
export type ViewConfigGetter = () => ReactNativeBaseComponentViewConfig<>;
/**
* Class only exists for its Flow type.
*/
class ReactNativeComponent<Props> extends React.Component<Props> {
blur(): void {}
focus(): void {}
measure(callback: MeasureOnSuccessCallback): void {}
measureInWindow(callback: MeasureInWindowOnSuccessCallback): void {}
measureLayout(
relativeToNativeNode: number | ElementRef<HostComponent<mixed>>,
onSuccess: MeasureLayoutOnSuccessCallback,
onFail?: () => void,
): void {}
setNativeProps(nativeProps: Object): void {}
}
// This type is only used for FlowTests. It shouldn't be imported directly
export type _InternalReactNativeComponentClass<Props> = Class<
ReactNativeComponent<Props>,
>;
/**
* This type keeps ReactNativeFiberHostComponent and NativeMethodsMixin in sync.
* It can also provide types for ReactNative applications that use NMM or refs.
*/
export type NativeMethods = {
blur(): void,
focus(): void,
@@ -116,28 +91,22 @@ export type NativeMethods = {
...
};
export type NativeMethodsMixinType = NativeMethods;
export type HostComponent<T> = AbstractComponent<T, $ReadOnly<NativeMethods>>;
type SecretInternalsType = {
NativeMethodsMixin: NativeMethodsMixinType,
computeComponentStackForErrorReporting(tag: number): string,
// TODO (bvaughn) Decide which additional types to expose here?
// And how much information to fill in for the above types.
...
};
type SecretInternalsFabricType = {
NativeMethodsMixin: NativeMethodsMixinType,
...
};
type SecretInternalsFabricType = {...};
/**
* Flat ReactNative renderer bundles are too big for Flow to parse efficiently.
* Provide minimal Flow typing for the high-level RN API and call it a day.
*/
export type ReactNativeType = {
NativeComponent: typeof ReactNativeComponent,
findHostInstance_DEPRECATED(
componentOrHandle: any,
): ?ElementRef<HostComponent<mixed>>,
@@ -157,7 +126,6 @@ export type ReactNativeType = {
};
export type ReactFabricType = {
NativeComponent: typeof ReactNativeComponent,
findHostInstance_DEPRECATED(componentOrHandle: any): ?HostComponent<mixed>,
findNodeHandle(componentOrHandle: any): ?number,
dispatchCommand(handle: any, command: string, args: Array<any>): void,
@@ -13,11 +13,9 @@
let React;
let ReactFabric;
let ReactFeatureFlags;
let createReactClass;
let createReactNativeComponentClass;
let UIManager;
let StrictMode;
let NativeMethodsMixin;
const SET_NATIVE_PROPS_NOT_SUPPORTED_MESSAGE =
'Warning: setNativeProps is not currently supported in Fabric';
@@ -42,16 +40,8 @@ describe('ReactFabric', () => {
ReactFeatureFlags = require('shared/ReactFeatureFlags');
UIManager = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
.UIManager;
createReactClass = require('create-react-class/factory')(
React.Component,
React.isValidElement,
new React.Component().updater,
);
createReactNativeComponentClass = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
.ReactNativeViewConfigRegistry.register;
NativeMethodsMixin =
ReactFabric.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
.NativeMethodsMixin;
});
it('should be able to create and render a native component', () => {
@@ -213,49 +203,34 @@ describe('ReactFabric', () => {
uiViewClassName: 'RCTView',
}));
class Subclass extends ReactFabric.NativeComponent {
render() {
return <View />;
}
}
UIManager.updateView.mockReset();
const CreateClass = createReactClass({
mixins: [NativeMethodsMixin],
render: () => {
return <View />;
},
let viewRef;
ReactFabric.render(
<View
foo="bar"
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
expect(UIManager.updateView).not.toBeCalled();
expect(() => {
viewRef.setNativeProps({});
}).toErrorDev([SET_NATIVE_PROPS_NOT_SUPPORTED_MESSAGE], {
withoutStack: true,
});
[View, Subclass, CreateClass].forEach(Component => {
UIManager.updateView.mockReset();
expect(UIManager.updateView).not.toBeCalled();
let viewRef;
ReactFabric.render(
<Component
foo="bar"
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
expect(UIManager.updateView).not.toBeCalled();
expect(() => {
viewRef.setNativeProps({});
}).toErrorDev([SET_NATIVE_PROPS_NOT_SUPPORTED_MESSAGE], {
withoutStack: true,
});
expect(UIManager.updateView).not.toBeCalled();
expect(() => {
viewRef.setNativeProps({foo: 'baz'});
}).toErrorDev([SET_NATIVE_PROPS_NOT_SUPPORTED_MESSAGE], {
withoutStack: true,
});
expect(UIManager.updateView).not.toBeCalled();
expect(() => {
viewRef.setNativeProps({foo: 'baz'});
}).toErrorDev([SET_NATIVE_PROPS_NOT_SUPPORTED_MESSAGE], {
withoutStack: true,
});
expect(UIManager.updateView).not.toBeCalled();
});
it('should call dispatchCommand for native refs', () => {
@@ -264,75 +239,53 @@ describe('ReactFabric', () => {
uiViewClassName: 'RCTView',
}));
[View].forEach(Component => {
nativeFabricUIManager.dispatchCommand.mockClear();
nativeFabricUIManager.dispatchCommand.mockClear();
let viewRef;
ReactFabric.render(
<Component
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
let viewRef;
ReactFabric.render(
<View
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
ReactFabric.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
expect(nativeFabricUIManager.dispatchCommand).toHaveBeenCalledTimes(1);
expect(
nativeFabricUIManager.dispatchCommand,
).toHaveBeenCalledWith(expect.any(Object), 'updateCommand', [10, 20]);
});
expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
ReactFabric.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
expect(nativeFabricUIManager.dispatchCommand).toHaveBeenCalledTimes(1);
expect(
nativeFabricUIManager.dispatchCommand,
).toHaveBeenCalledWith(expect.any(Object), 'updateCommand', [10, 20]);
});
it('should warn and no-op if calling dispatchCommand on non native refs', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
uiViewClassName: 'RCTView',
}));
class BasicClass extends React.Component {
render() {
return <React.Fragment />;
}
}
class Subclass extends ReactFabric.NativeComponent {
render() {
return <View />;
}
}
nativeFabricUIManager.dispatchCommand.mockReset();
const CreateClass = createReactClass({
mixins: [NativeMethodsMixin],
render: () => {
return <View />;
},
let viewRef;
ReactFabric.render(
<BasicClass
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
expect(() => {
ReactFabric.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
}).toErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT], {
withoutStack: true,
});
[BasicClass, Subclass, CreateClass].forEach(Component => {
nativeFabricUIManager.dispatchCommand.mockReset();
let viewRef;
ReactFabric.render(
<Component
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
expect(() => {
ReactFabric.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
}).toErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT], {
withoutStack: true,
});
expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
});
expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
});
it('should call FabricUIManager.measure on ref.measure', () => {
@@ -341,39 +294,24 @@ describe('ReactFabric', () => {
uiViewClassName: 'RCTView',
}));
class Subclass extends ReactFabric.NativeComponent {
render() {
return <View>{this.props.children}</View>;
}
}
nativeFabricUIManager.measure.mockClear();
const CreateClass = createReactClass({
mixins: [NativeMethodsMixin],
render() {
return <View>{this.props.children}</View>;
},
});
let viewRef;
ReactFabric.render(
<View
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
[View, Subclass, CreateClass].forEach(Component => {
nativeFabricUIManager.measure.mockClear();
let viewRef;
ReactFabric.render(
<Component
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
expect(nativeFabricUIManager.measure).not.toBeCalled();
const successCallback = jest.fn();
viewRef.measure(successCallback);
expect(nativeFabricUIManager.measure).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100, 0, 0);
});
expect(nativeFabricUIManager.measure).not.toBeCalled();
const successCallback = jest.fn();
viewRef.measure(successCallback);
expect(nativeFabricUIManager.measure).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100, 0, 0);
});
it('should call FabricUIManager.measureInWindow on ref.measureInWindow', () => {
@@ -382,39 +320,24 @@ describe('ReactFabric', () => {
uiViewClassName: 'RCTView',
}));
class Subclass extends ReactFabric.NativeComponent {
render() {
return <View>{this.props.children}</View>;
}
}
nativeFabricUIManager.measureInWindow.mockClear();
const CreateClass = createReactClass({
mixins: [NativeMethodsMixin],
render() {
return <View>{this.props.children}</View>;
},
});
let viewRef;
ReactFabric.render(
<View
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
[View, Subclass, CreateClass].forEach(Component => {
nativeFabricUIManager.measureInWindow.mockClear();
let viewRef;
ReactFabric.render(
<Component
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
expect(nativeFabricUIManager.measureInWindow).not.toBeCalled();
const successCallback = jest.fn();
viewRef.measureInWindow(successCallback);
expect(nativeFabricUIManager.measureInWindow).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100);
});
expect(nativeFabricUIManager.measureInWindow).not.toBeCalled();
const successCallback = jest.fn();
viewRef.measureInWindow(successCallback);
expect(nativeFabricUIManager.measureInWindow).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100);
});
it('should support ref in ref.measureLayout', () => {
@@ -423,98 +346,34 @@ describe('ReactFabric', () => {
uiViewClassName: 'RCTView',
}));
[View].forEach(Component => {
nativeFabricUIManager.measureLayout.mockClear();
nativeFabricUIManager.measureLayout.mockClear();
let viewRef;
let otherRef;
ReactFabric.render(
<Component>
<Component
foo="bar"
ref={ref => {
viewRef = ref;
}}
/>
<View
ref={ref => {
otherRef = ref;
}}
/>
</Component>,
11,
);
let viewRef;
let otherRef;
ReactFabric.render(
<View>
<View
foo="bar"
ref={ref => {
viewRef = ref;
}}
/>
<View
ref={ref => {
otherRef = ref;
}}
/>
</View>,
11,
);
expect(nativeFabricUIManager.measureLayout).not.toBeCalled();
const successCallback = jest.fn();
const failureCallback = jest.fn();
viewRef.measureLayout(otherRef, successCallback, failureCallback);
expect(nativeFabricUIManager.measureLayout).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(1, 1, 100, 100);
});
});
it('should warn when calling measureLayout on Subclass and NativeMethodsMixin', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
uiViewClassName: 'RCTView',
}));
class Subclass extends ReactFabric.NativeComponent {
render() {
return <View>{this.props.children}</View>;
}
}
const CreateClass = createReactClass({
mixins: [NativeMethodsMixin],
render() {
return <View>{this.props.children}</View>;
},
});
[Subclass, CreateClass].forEach(Component => {
nativeFabricUIManager.measureLayout.mockReset();
let viewRef;
let otherRef;
ReactFabric.render(
<Component>
<Component
foo="bar"
ref={ref => {
viewRef = ref;
}}
/>
<View
ref={ref => {
otherRef = ref;
}}
/>
</Component>,
11,
);
const successCallback = jest.fn();
const failureCallback = jest.fn();
expect(() => {
viewRef.measureLayout(otherRef, successCallback, failureCallback);
}).toErrorDev(
[
'Warning: measureLayout on components using NativeMethodsMixin ' +
'or ReactNative.NativeComponent is not currently supported in Fabric. ' +
'measureLayout must be called on a native ref. Consider using forwardRef.',
],
{
withoutStack: true,
},
);
expect(nativeFabricUIManager.measureLayout).not.toBeCalled();
expect(UIManager.measureLayout).not.toBeCalled();
});
expect(nativeFabricUIManager.measureLayout).not.toBeCalled();
const successCallback = jest.fn();
const failureCallback = jest.fn();
viewRef.measureLayout(otherRef, successCallback, failureCallback);
expect(nativeFabricUIManager.measureLayout).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(1, 1, 100, 100);
});
it('returns the correct instance and calls it in the callback', () => {
@@ -13,10 +13,8 @@
let React;
let StrictMode;
let ReactNative;
let createReactClass;
let createReactNativeComponentClass;
let UIManager;
let NativeMethodsMixin;
const DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT =
"Warning: dispatchCommand was called with a ref that isn't a " +
@@ -31,16 +29,8 @@ describe('ReactNative', () => {
ReactNative = require('react-native-renderer');
UIManager = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
.UIManager;
createReactClass = require('create-react-class/factory')(
React.Component,
React.isValidElement,
new React.Component().updater,
);
createReactNativeComponentClass = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
.ReactNativeViewConfigRegistry.register;
NativeMethodsMixin =
ReactNative.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
.NativeMethodsMixin;
});
it('should be able to create and render a native component', () => {
@@ -109,75 +99,53 @@ describe('ReactNative', () => {
uiViewClassName: 'RCTView',
}));
[View].forEach(Component => {
UIManager.dispatchViewManagerCommand.mockClear();
UIManager.dispatchViewManagerCommand.mockClear();
let viewRef;
ReactNative.render(
<Component
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
let viewRef;
ReactNative.render(
<View
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
ReactNative.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledTimes(1);
expect(
UIManager.dispatchViewManagerCommand,
).toHaveBeenCalledWith(expect.any(Number), 'updateCommand', [10, 20]);
});
expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
ReactNative.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
expect(UIManager.dispatchViewManagerCommand).toHaveBeenCalledTimes(1);
expect(
UIManager.dispatchViewManagerCommand,
).toHaveBeenCalledWith(expect.any(Number), 'updateCommand', [10, 20]);
});
it('should warn and no-op if calling dispatchCommand on non native refs', () => {
const View = createReactNativeComponentClass('RCTView', () => ({
validAttributes: {foo: true},
uiViewClassName: 'RCTView',
}));
class BasicClass extends React.Component {
render() {
return <React.Fragment />;
}
}
class Subclass extends ReactNative.NativeComponent {
render() {
return <View />;
}
}
UIManager.dispatchViewManagerCommand.mockReset();
const CreateClass = createReactClass({
mixins: [NativeMethodsMixin],
render: () => {
return <View />;
},
let viewRef;
ReactNative.render(
<BasicClass
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
expect(() => {
ReactNative.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
}).toErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT], {
withoutStack: true,
});
[BasicClass, Subclass, CreateClass].forEach(Component => {
UIManager.dispatchViewManagerCommand.mockReset();
let viewRef;
ReactNative.render(
<Component
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
expect(() => {
ReactNative.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
}).toErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT], {
withoutStack: true,
});
expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
});
expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
});
it('should not call UIManager.updateView from ref.setNativeProps for properties that have not changed', () => {
@@ -186,46 +154,31 @@ describe('ReactNative', () => {
uiViewClassName: 'RCTView',
}));
class Subclass extends ReactNative.NativeComponent {
render() {
return <View />;
}
}
UIManager.updateView.mockReset();
const CreateClass = createReactClass({
mixins: [NativeMethodsMixin],
render: () => {
return <View />;
},
});
let viewRef;
ReactNative.render(
<View
foo="bar"
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
[View, Subclass, CreateClass].forEach(Component => {
UIManager.updateView.mockReset();
expect(UIManager.updateView).not.toBeCalled();
let viewRef;
ReactNative.render(
<Component
foo="bar"
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
viewRef.setNativeProps({});
expect(UIManager.updateView).not.toBeCalled();
expect(UIManager.updateView).not.toBeCalled();
viewRef.setNativeProps({});
expect(UIManager.updateView).not.toBeCalled();
viewRef.setNativeProps({foo: 'baz'});
expect(UIManager.updateView).toHaveBeenCalledTimes(1);
expect(UIManager.updateView).toHaveBeenCalledWith(
expect.any(Number),
'RCTView',
{foo: 'baz'},
);
});
viewRef.setNativeProps({foo: 'baz'});
expect(UIManager.updateView).toHaveBeenCalledTimes(1);
expect(UIManager.updateView).toHaveBeenCalledWith(
expect.any(Number),
'RCTView',
{foo: 'baz'},
);
});
it('should call UIManager.measure on ref.measure', () => {
@@ -234,39 +187,24 @@ describe('ReactNative', () => {
uiViewClassName: 'RCTView',
}));
class Subclass extends ReactNative.NativeComponent {
render() {
return <View>{this.props.children}</View>;
}
}
UIManager.measure.mockClear();
const CreateClass = createReactClass({
mixins: [NativeMethodsMixin],
render() {
return <View>{this.props.children}</View>;
},
});
let viewRef;
ReactNative.render(
<View
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
[View, Subclass, CreateClass].forEach(Component => {
UIManager.measure.mockClear();
let viewRef;
ReactNative.render(
<Component
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
expect(UIManager.measure).not.toBeCalled();
const successCallback = jest.fn();
viewRef.measure(successCallback);
expect(UIManager.measure).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100, 0, 0);
});
expect(UIManager.measure).not.toBeCalled();
const successCallback = jest.fn();
viewRef.measure(successCallback);
expect(UIManager.measure).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100, 0, 0);
});
it('should call UIManager.measureInWindow on ref.measureInWindow', () => {
@@ -275,39 +213,24 @@ describe('ReactNative', () => {
uiViewClassName: 'RCTView',
}));
class Subclass extends ReactNative.NativeComponent {
render() {
return <View>{this.props.children}</View>;
}
}
UIManager.measureInWindow.mockClear();
const CreateClass = createReactClass({
mixins: [NativeMethodsMixin],
render() {
return <View>{this.props.children}</View>;
},
});
let viewRef;
ReactNative.render(
<View
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
[View, Subclass, CreateClass].forEach(Component => {
UIManager.measureInWindow.mockClear();
let viewRef;
ReactNative.render(
<Component
ref={ref => {
viewRef = ref;
}}
/>,
11,
);
expect(UIManager.measureInWindow).not.toBeCalled();
const successCallback = jest.fn();
viewRef.measureInWindow(successCallback);
expect(UIManager.measureInWindow).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100);
});
expect(UIManager.measureInWindow).not.toBeCalled();
const successCallback = jest.fn();
viewRef.measureInWindow(successCallback);
expect(UIManager.measureInWindow).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(10, 10, 100, 100);
});
it('should support reactTag in ref.measureLayout', () => {
@@ -316,53 +239,38 @@ describe('ReactNative', () => {
uiViewClassName: 'RCTView',
}));
class Subclass extends ReactNative.NativeComponent {
render() {
return <View>{this.props.children}</View>;
}
}
UIManager.measureLayout.mockClear();
const CreateClass = createReactClass({
mixins: [NativeMethodsMixin],
render() {
return <View>{this.props.children}</View>;
},
});
let viewRef;
let otherRef;
ReactNative.render(
<View>
<View
foo="bar"
ref={ref => {
viewRef = ref;
}}
/>
<View
ref={ref => {
otherRef = ref;
}}
/>
</View>,
11,
);
[View, Subclass, CreateClass].forEach(Component => {
UIManager.measureLayout.mockClear();
let viewRef;
let otherRef;
ReactNative.render(
<Component>
<Component
foo="bar"
ref={ref => {
viewRef = ref;
}}
/>
<Component
ref={ref => {
otherRef = ref;
}}
/>
</Component>,
11,
);
expect(UIManager.measureLayout).not.toBeCalled();
const successCallback = jest.fn();
const failureCallback = jest.fn();
viewRef.measureLayout(
ReactNative.findNodeHandle(otherRef),
successCallback,
failureCallback,
);
expect(UIManager.measureLayout).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(1, 1, 100, 100);
});
expect(UIManager.measureLayout).not.toBeCalled();
const successCallback = jest.fn();
const failureCallback = jest.fn();
viewRef.measureLayout(
ReactNative.findNodeHandle(otherRef),
successCallback,
failureCallback,
);
expect(UIManager.measureLayout).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(1, 1, 100, 100);
});
it('should support ref in ref.measureLayout of host components', () => {
@@ -371,36 +279,34 @@ describe('ReactNative', () => {
uiViewClassName: 'RCTView',
}));
[View].forEach(Component => {
UIManager.measureLayout.mockClear();
UIManager.measureLayout.mockClear();
let viewRef;
let otherRef;
ReactNative.render(
<Component>
<Component
foo="bar"
ref={ref => {
viewRef = ref;
}}
/>
<View
ref={ref => {
otherRef = ref;
}}
/>
</Component>,
11,
);
let viewRef;
let otherRef;
ReactNative.render(
<View>
<View
foo="bar"
ref={ref => {
viewRef = ref;
}}
/>
<View
ref={ref => {
otherRef = ref;
}}
/>
</View>,
11,
);
expect(UIManager.measureLayout).not.toBeCalled();
const successCallback = jest.fn();
const failureCallback = jest.fn();
viewRef.measureLayout(otherRef, successCallback, failureCallback);
expect(UIManager.measureLayout).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(1, 1, 100, 100);
});
expect(UIManager.measureLayout).not.toBeCalled();
const successCallback = jest.fn();
const failureCallback = jest.fn();
viewRef.measureLayout(otherRef, successCallback, failureCallback);
expect(UIManager.measureLayout).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledTimes(1);
expect(successCallback).toHaveBeenCalledWith(1, 1, 100, 100);
});
it('returns the correct instance and calls it in the callback', () => {
@@ -1,74 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails react-core
*/
'use strict';
describe('create-react-class-integration', () => {
describe('ReactNative NativeMethodsMixin', () => {
let React;
let ReactNative;
let NativeMethodsMixin;
let createReactClass;
beforeEach(() => {
jest.resetModules();
React = require('react');
createReactClass = require('create-react-class/factory')(
React.Component,
React.isValidElement,
new React.Component().updater,
);
ReactNative = require('react-native-renderer');
NativeMethodsMixin =
ReactNative.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
.NativeMethodsMixin;
});
it('should not warn about default DEV-only legacy lifecycle methods', () => {
const View = createReactClass({
mixins: [NativeMethodsMixin],
render: () => null,
});
ReactNative.render(<View />, 1);
});
it('should warn if users specify their own legacy componentWillMount', () => {
const View = createReactClass({
displayName: 'MyNativeComponent',
mixins: [NativeMethodsMixin],
componentWillMount: () => {},
render: () => null,
});
expect(() =>
ReactNative.render(<View />, 1),
).toWarnDev('componentWillMount has been renamed', {withoutStack: true});
});
it('should warn if users specify their own legacy componentWillReceiveProps', () => {
const View = createReactClass({
displayName: 'MyNativeComponent',
mixins: [NativeMethodsMixin],
componentWillReceiveProps: () => {},
render: () => null,
});
expect(() => ReactNative.render(<View />, 1)).toWarnDev(
'componentWillReceiveProps has been renamed',
{
withoutStack: true,
},
);
});
});
});
-21
View File
@@ -1,21 +0,0 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/
'use strict';
const {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
} = require('./ReactNative');
import type {NativeMethodsMixinType} from './ReactNativeTypes';
const {NativeMethodsMixin} = __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
module.exports = ((NativeMethodsMixin: any): $Exact<NativeMethodsMixinType>);