diff --git a/packages/react-native-renderer/src/ReactFabricHostConfig.js b/packages/react-native-renderer/src/ReactFabricHostConfig.js
index 959860bcf2cbb..6e371f9ff8cd0 100644
--- a/packages/react-native-renderer/src/ReactFabricHostConfig.js
+++ b/packages/react-native-renderer/src/ReactFabricHostConfig.js
@@ -104,11 +104,11 @@ class ReactFabricHostComponent {
}
blur() {
- TextInputState.blurTextInput(this._nativeTag);
+ TextInputState.blurTextInput(this);
}
focus() {
- TextInputState.focusTextInput(this._nativeTag);
+ TextInputState.focusTextInput(this);
}
measure(callback: MeasureOnSuccessCallback) {
diff --git a/packages/react-native-renderer/src/ReactNativeFiberHostComponent.js b/packages/react-native-renderer/src/ReactNativeFiberHostComponent.js
index ba316e010c7a5..c4c74462a4d7e 100644
--- a/packages/react-native-renderer/src/ReactNativeFiberHostComponent.js
+++ b/packages/react-native-renderer/src/ReactNativeFiberHostComponent.js
@@ -40,11 +40,11 @@ class ReactNativeFiberHostComponent {
}
blur() {
- TextInputState.blurTextInput(this._nativeTag);
+ TextInputState.blurTextInput(this);
}
focus() {
- TextInputState.focusTextInput(this._nativeTag);
+ TextInputState.focusTextInput(this);
}
measure(callback: MeasureOnSuccessCallback) {
diff --git a/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/TextInputState.js b/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/TextInputState.js
index cc97ef5b1852a..cad828edaea7e 100644
--- a/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/TextInputState.js
+++ b/packages/react-native-renderer/src/__mocks__/react-native/Libraries/ReactPrivate/TextInputState.js
@@ -10,6 +10,9 @@
// Mock of the Native Hooks
// TODO: Should this move into the components themselves? E.g. focusable
-const TextInputState = {};
+const TextInputState = {
+ blurTextInput: jest.fn(),
+ focusTextInput: jest.fn(),
+};
module.exports = TextInputState;
diff --git a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js
index 0929b80e36b56..2143957d19e5b 100644
--- a/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js
+++ b/packages/react-native-renderer/src/__tests__/ReactFabric-test.internal.js
@@ -16,6 +16,7 @@ let ReactFeatureFlags;
let createReactNativeComponentClass;
let UIManager;
let StrictMode;
+let TextInputState;
const SET_NATIVE_PROPS_NOT_SUPPORTED_MESSAGE =
'Warning: setNativeProps is not currently supported in Fabric';
@@ -42,6 +43,8 @@ describe('ReactFabric', () => {
.UIManager;
createReactNativeComponentClass = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
.ReactNativeViewConfigRegistry.register;
+ TextInputState = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
+ .TextInputState;
});
it('should be able to create and render a native component', () => {
@@ -991,4 +994,38 @@ describe('ReactFabric', () => {
]);
expect(match).toBe(child._nativeTag);
});
+
+ it('blur on host component calls TextInputState', () => {
+ const View = createReactNativeComponentClass('RCTView', () => ({
+ validAttributes: {foo: true},
+ uiViewClassName: 'RCTView',
+ }));
+
+ let viewRef = React.createRef();
+ ReactFabric.render(, 11);
+
+ expect(TextInputState.blurTextInput).not.toBeCalled();
+
+ viewRef.current.blur();
+
+ expect(TextInputState.blurTextInput).toHaveBeenCalledTimes(1);
+ expect(TextInputState.blurTextInput).toHaveBeenCalledWith(viewRef.current);
+ });
+
+ it('focus on host component calls TextInputState', () => {
+ const View = createReactNativeComponentClass('RCTView', () => ({
+ validAttributes: {foo: true},
+ uiViewClassName: 'RCTView',
+ }));
+
+ let viewRef = React.createRef();
+ ReactFabric.render(, 11);
+
+ expect(TextInputState.focusTextInput).not.toBeCalled();
+
+ viewRef.current.focus();
+
+ expect(TextInputState.focusTextInput).toHaveBeenCalledTimes(1);
+ expect(TextInputState.focusTextInput).toHaveBeenCalledWith(viewRef.current);
+ });
});
diff --git a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js
index 395cac0c20d8c..75b2ce286c148 100644
--- a/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js
+++ b/packages/react-native-renderer/src/__tests__/ReactNativeMount-test.internal.js
@@ -15,6 +15,7 @@ let StrictMode;
let ReactNative;
let createReactNativeComponentClass;
let UIManager;
+let TextInputState;
const DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT =
"Warning: dispatchCommand was called with a ref that isn't a " +
@@ -31,6 +32,8 @@ describe('ReactNative', () => {
.UIManager;
createReactNativeComponentClass = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
.ReactNativeViewConfigRegistry.register;
+ TextInputState = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
+ .TextInputState;
});
it('should be able to create and render a native component', () => {
@@ -594,4 +597,38 @@ describe('ReactNative', () => {
]);
expect(match).toBe(child._nativeTag);
});
+
+ it('blur on host component calls TextInputState', () => {
+ const View = createReactNativeComponentClass('RCTView', () => ({
+ validAttributes: {foo: true},
+ uiViewClassName: 'RCTView',
+ }));
+
+ let viewRef = React.createRef();
+ ReactNative.render(, 11);
+
+ expect(TextInputState.blurTextInput).not.toBeCalled();
+
+ viewRef.current.blur();
+
+ expect(TextInputState.blurTextInput).toHaveBeenCalledTimes(1);
+ expect(TextInputState.blurTextInput).toHaveBeenCalledWith(viewRef.current);
+ });
+
+ it('focus on host component calls TextInputState', () => {
+ const View = createReactNativeComponentClass('RCTView', () => ({
+ validAttributes: {foo: true},
+ uiViewClassName: 'RCTView',
+ }));
+
+ let viewRef = React.createRef();
+ ReactNative.render(, 11);
+
+ expect(TextInputState.focusTextInput).not.toBeCalled();
+
+ viewRef.current.focus();
+
+ expect(TextInputState.focusTextInput).toHaveBeenCalledTimes(1);
+ expect(TextInputState.focusTextInput).toHaveBeenCalledWith(viewRef.current);
+ });
});