mirror of
https://github.com/facebook/react.git
synced 2026-02-26 18:58:05 +00:00
* Deprecate ref.setNativeProps in favor of ReactNative.setNativeProps * Using a feature flag for the setNativeProps warning * Removing extra line breaks * Set the FB native feature flag to true * Prettier
196 lines
6.5 KiB
JavaScript
196 lines
6.5 KiB
JavaScript
/**
|
|
* 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,
|
|
NativeMethodsMixinType,
|
|
ReactNativeBaseComponentViewConfig,
|
|
} from './ReactNativeTypes';
|
|
|
|
import React from 'react';
|
|
// Modules provided by RN:
|
|
import TextInputState from 'TextInputState';
|
|
import UIManager from 'UIManager';
|
|
|
|
import {create} from './ReactNativeAttributePayload';
|
|
import {mountSafeCallback_NOT_REALLY_SAFE} from './NativeMethodsMixinUtils';
|
|
|
|
import warningWithoutStack from 'shared/warningWithoutStack';
|
|
import {warnAboutDeprecatedSetNativeProps} from 'shared/ReactFeatureFlags';
|
|
|
|
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, State = void> extends React.Component<
|
|
Props,
|
|
State,
|
|
> {
|
|
/**
|
|
* 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;
|
|
state: State;
|
|
|
|
/**
|
|
* 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 {
|
|
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 {
|
|
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,
|
|
onSuccess: MeasureLayoutOnSuccessCallback,
|
|
onFail: () => void /* currently unused */,
|
|
): void {
|
|
UIManager.measureLayout(
|
|
findNodeHandle(this),
|
|
relativeToNativeNode,
|
|
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 {
|
|
if (__DEV__) {
|
|
if (warnAboutDeprecatedSetNativeProps) {
|
|
warningWithoutStack(
|
|
false,
|
|
'Warning: Calling ref.setNativeProps(nativeProps) ' +
|
|
'is deprecated and will be removed in a future release. ' +
|
|
'Use the setNativeProps export from the react-native package instead.' +
|
|
"\n\timport {setNativeProps} from 'react-native';\n\tsetNativeProps(ref, nativeProps);\n",
|
|
);
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
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: NativeMethodsMixinType);
|
|
|
|
return ReactNativeComponent;
|
|
}
|