diff --git a/packages/react-native-aztec/src/AztecInputState.js b/packages/react-native-aztec/src/AztecInputState.js index b688ef04ce26e0..f76f8ed4f24501 100644 --- a/packages/react-native-aztec/src/AztecInputState.js +++ b/packages/react-native-aztec/src/AztecInputState.js @@ -142,7 +142,7 @@ export const focus = ( element ) => { // will take precedence and cancels pending blur events. blur.cancel(); // Similar to blur events, we also need to cancel potential keyboard dismiss. - dismissKeyboardDebounce.cancel(); + blurOnUnmountDebounce.cancel(); TextInputState.focusTextInput( element ); notifyInputChange(); @@ -164,13 +164,6 @@ export const blur = debounce( ( element ) => { /** * Unfocuses the specified element in case it's about to be unmounted. * - * On iOS text inputs are automatically unfocused and keyboard dismissed when they - * are removed. However, this is not the case on Android, where text inputs are - * unfocused but the keyboard remains open. - * - * For dismissing the keyboard, we use debounce to avoid conflicts with the focus - * event when both are triggered at the same time. - * * Note that we can't trigger the blur event, as it's likely that the Aztec view is no * longer available when the event is executed and will produce an exception. * @@ -181,15 +174,24 @@ export const blurOnUnmount = ( element ) => { // If a blur event was triggered before unmount, we need to cancel them to avoid // exceptions. blur.cancel(); - if ( Platform.OS === 'android' ) { - dismissKeyboardDebounce(); - } + blurOnUnmountDebounce(); } }; -const dismissKeyboardDebounce = debounce( () => { - hideAndroidSoftKeyboard(); +// For updating the input state and dismissing the keyboard, we use debounce to avoid +// conflicts with the focus event when both are triggered at the same time. +const blurOnUnmountDebounce = debounce( () => { + // At this point, the text input will be destroyed but it's still focused. Hence, we + // have to explicitly notify listeners and update internal input state. + notifyListeners( { isFocused: false } ); currentFocusedElement = null; + + // On iOS text inputs are automatically unfocused and keyboard dismissed when they + // are removed. However, this is not the case on Android, where text inputs are + // unfocused but the keyboard remains open. + if ( Platform.OS === 'android' ) { + hideAndroidSoftKeyboard(); + } }, 0 ); /** diff --git a/packages/react-native-aztec/src/test/AztecInputState.test.js b/packages/react-native-aztec/src/test/AztecInputState.test.js index e95d25a695c964..1458508a892e84 100644 --- a/packages/react-native-aztec/src/test/AztecInputState.test.js +++ b/packages/react-native-aztec/src/test/AztecInputState.test.js @@ -12,6 +12,7 @@ import { isFocused, focus, blur, + blurOnUnmount, notifyInputChange, removeFocusChangeListener, } from '../AztecInputState'; @@ -101,4 +102,16 @@ describe( 'Aztec Input State', () => { jest.runAllTimers(); expect( TextInputState.blurTextInput ).toHaveBeenCalledWith( ref ); } ); + + it( 'unfocuses an element when unmounted', () => { + const listener = jest.fn(); + addFocusChangeListener( listener ); + + updateCurrentFocusedInput( ref ); + blurOnUnmount( ref ); + jest.runAllTimers(); + + expect( listener ).toHaveBeenCalledWith( { isFocused: false } ); + expect( isFocused() ).toBeFalsy(); + } ); } );