Skip to content

Commit

Permalink
[RNMobile] Ensure Aztec input state function blurOnUnmount updates …
Browse files Browse the repository at this point in the history
…its state (#57486)

* Ensure `blurOnUnmount` updates internal input state

* Add unit test to cover `blurOnUnmount` logic
  • Loading branch information
fluiddot authored Jan 2, 2024
1 parent 0e70eb3 commit 63a0e09
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 13 deletions.
28 changes: 15 additions & 13 deletions packages/react-native-aztec/src/AztecInputState.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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.
*
Expand All @@ -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 );

/**
Expand Down
13 changes: 13 additions & 0 deletions packages/react-native-aztec/src/test/AztecInputState.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
isFocused,
focus,
blur,
blurOnUnmount,
notifyInputChange,
removeFocusChangeListener,
} from '../AztecInputState';
Expand Down Expand Up @@ -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();
} );
} );

0 comments on commit 63a0e09

Please sign in to comment.