Skip to content

Commit

Permalink
Fix race condition in KeyboardAvoidingView
Browse files Browse the repository at this point in the history
Summary:
Changelog: Fix possible race condition inside `KeyboardAvoidingView`

Fabric has different order of events

In Fabric, `keyboardWillChangeFrame` event is fired before `onLayout`, but in Paper it is the other way around.
`KeyboardAvoidingView` depends on the order of events to function properly. Inside `_relativeKeyboardHeight` 0 is returned if `this._frame` is null.

To fix this, `bottom` margin is recalculated whenever `keyboardWillChangeFrame` or `onLayout` is triggered.

Reviewed By: shergin

Differential Revision: D22764192

fbshipit-source-id: 591ac59af4395a4d43c4e78e4fbc0ff118b292f8
  • Loading branch information
sammy-SC authored and facebook-github-bot committed Jul 27, 2020
1 parent 7c7f09e commit b08fff6
Showing 1 changed file with 18 additions and 10 deletions.
28 changes: 18 additions & 10 deletions Libraries/Components/Keyboard/KeyboardAvoidingView.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
};

_frame: ?ViewLayout = null;
_keyboardEvent: ?KeyboardEvent = null;
_subscriptions: Array<EventSubscription> = [];
viewRef: {current: React.ElementRef<any> | null, ...};
_initialFrameHeight: number = 0;
Expand All @@ -91,12 +92,27 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
}

_onKeyboardChange = (event: ?KeyboardEvent) => {
if (event == null) {
this._keyboardEvent = event;
this._updateBottomIfNecesarry();
};

_onLayout = (event: ViewLayoutEvent) => {
this._frame = event.nativeEvent.layout;
if (!this._initialFrameHeight) {
// save the initial frame height, before the keyboard is visible
this._initialFrameHeight = this._frame.height;
}

this._updateBottomIfNecesarry();
};

_updateBottomIfNecesarry = () => {

This comment has been minimized.

Copy link
@andres-torres-marroquin

andres-torres-marroquin Mar 4, 2021

Is it Necesarry or Necessary? 😬

if (this._keyboardEvent == null) {
this.setState({bottom: 0});
return;
}

const {duration, easing, endCoordinates} = event;
const {duration, easing, endCoordinates} = this._keyboardEvent;
const height = this._relativeKeyboardHeight(endCoordinates);

if (this.state.bottom === height) {
Expand All @@ -116,14 +132,6 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
this.setState({bottom: height});
};

_onLayout = (event: ViewLayoutEvent) => {
this._frame = event.nativeEvent.layout;
if (!this._initialFrameHeight) {
// save the initial frame height, before the keyboard is visible
this._initialFrameHeight = this._frame.height;
}
};

componentDidMount(): void {
if (Platform.OS === 'ios') {
this._subscriptions = [
Expand Down

0 comments on commit b08fff6

Please sign in to comment.