Skip to content

Commit

Permalink
Don't use setState for disabled KeyboardAvoidingView to avoid re-rend…
Browse files Browse the repository at this point in the history
…ers (#38074)

Summary:
There are two reasons to apply these changes:
- We don't need to re-render the `KeyboardAvoidingView` if it is disabled. It may be especially useful in combination with [react-navigation](https://reactnavigation.org/) where we could disable `KeyboardAvoidingView` for screens that are not focused
- They fix the problem with the `KeyboardAvoidingView` wrapped inside the [react-freeze](https://github.com/software-mansion/react-freeze) component. Similarly, as above, it is useful when we want to freeze screens that are not visible for the user.

## Changelog:
[GENERAL] [CHANGED] Don't use setState for disabled KeyboardAvoidingView to avoid re-renders

<!-- Help reviewers and the release process by writing your own changelog entry.

Pick one each for the category and type tags:

[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message

For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests

Pull Request resolved: #38074

Test Plan: - Check if the KeyboardAvoidingView works as expected.

Reviewed By: sammy-SC

Differential Revision: D49148391

Pulled By: blakef

fbshipit-source-id: c4b7bde696d2249cbf4ad12c77058183b632464d
  • Loading branch information
adamgrzybowski authored and facebook-github-bot committed Sep 21, 2023
1 parent 1e44a5f commit 783150f
Showing 1 changed file with 23 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
_subscriptions: Array<EventSubscription> = [];
viewRef: {current: React.ElementRef<typeof View> | null, ...};
_initialFrameHeight: number = 0;
_bottom: number = 0;

constructor(props: Props) {
super(props);
Expand Down Expand Up @@ -129,20 +130,32 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
}
};

// Avoid unnecessary renders if the KeyboardAvoidingView is disabled.
_setBottom = (value: number) => {
const enabled = this.props.enabled ?? true;
this._bottom = value;
if (enabled) {
this.setState({bottom: value});
}
};

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

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

if (this.state.bottom === height) {
if (this._bottom === height) {
return;
}

if (duration && easing) {
this._setBottom(height);

const enabled = this.props.enabled ?? true;
if (enabled && duration && easing) {
LayoutAnimation.configureNext({
// We have to pass the duration equal to minimal accepted duration defined here: RCTLayoutAnimation.m
duration: duration > 10 ? duration : 10,
Expand All @@ -152,9 +165,15 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
},
});
}
this.setState({bottom: height});
};

componentDidUpdate(_: Props, prevState: State): void {
const enabled = this.props.enabled ?? true;
if (enabled && this._bottom !== prevState.bottom) {
this.setState({bottom: this._bottom});
}
}

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

0 comments on commit 783150f

Please sign in to comment.