@@ -21,6 +21,10 @@ import {
2121
2222import { KeyboardProvider } from '../../contexts/keyboardContext/KeyboardContext' ;
2323
24+ type State = {
25+ bottom : number ;
26+ } ;
27+
2428/**
2529 * View that moves out of the way when the keyboard appears by automatically
2630 * adjusting its height, position, or bottom padding.
@@ -46,6 +50,8 @@ export class KeyboardCompatibleView extends React.Component<
4650 _appStateSubscription : NativeEventSubscription | null = null ;
4751 viewRef : React . RefObject < View | null > ;
4852 _initialFrameHeight = 0 ;
53+ _bottom : number = 0 ;
54+
4955 constructor ( props : KeyboardAvoidingViewProps ) {
5056 super ( props ) ;
5157 this . state = {
@@ -93,28 +99,49 @@ export class KeyboardCompatibleView extends React.Component<
9399 } ;
94100
95101 _onLayout : ( event : LayoutChangeEvent ) => void = ( event ) => {
102+ event . persist ( ) ;
103+
104+ const oldFrame = this . _frame ;
96105 this . _frame = event . nativeEvent . layout ;
97106 if ( ! this . _initialFrameHeight ) {
98107 // save the initial frame height, before the keyboard is visible
99108 this . _initialFrameHeight = this . _frame . height ;
100109 }
101110
102- this . _updateBottomIfNecessary ( ) ;
111+ // update bottom height for the first time or when the height is changed
112+ if ( ! oldFrame || oldFrame . height !== this . _frame . height ) {
113+ this . _updateBottomIfNecessary ( ) ;
114+ }
115+
116+ if ( this . props . onLayout ) {
117+ this . props . onLayout ( event ) ;
118+ }
119+ } ;
120+
121+ // Avoid unnecessary renders if the KeyboardAvoidingView is disabled.
122+ _setBottom = ( value : number ) => {
123+ const enabled = this . props . enabled ?? true ;
124+ this . _bottom = value ;
125+ if ( enabled ) {
126+ this . setState ( { bottom : value } ) ;
127+ }
103128 } ;
104129
105130 _updateBottomIfNecessary = ( ) => {
106- if ( this . _keyboardEvent === null ) {
107- this . setState ( { bottom : 0 } ) ;
131+ if ( this . _keyboardEvent == null ) {
132+ this . _setBottom ( 0 ) ;
108133 return ;
109134 }
110135
111136 const { duration, easing, endCoordinates } = this . _keyboardEvent ;
112137 const height = this . _relativeKeyboardHeight ( endCoordinates ) ;
113138
114- if ( this . state . bottom === height ) {
139+ if ( this . _bottom === height ) {
115140 return ;
116141 }
117142
143+ this . _setBottom ( height ) ;
144+
118145 if ( duration && easing ) {
119146 LayoutAnimation . configureNext ( {
120147 // We have to pass the duration equal to minimal accepted duration defined here: RCTLayoutAnimation.m
@@ -125,7 +152,6 @@ export class KeyboardCompatibleView extends React.Component<
125152 } ,
126153 } ) ;
127154 }
128- this . setState ( { bottom : height } ) ;
129155 } ;
130156
131157 _handleAppStateChange = ( nextAppState : AppStateStatus ) => {
@@ -184,6 +210,13 @@ export class KeyboardCompatibleView extends React.Component<
184210 } ) ;
185211 } ;
186212
213+ componentDidUpdate ( _ : KeyboardAvoidingViewProps , prevState : State ) : void {
214+ const enabled = this . props . enabled ?? true ;
215+ if ( enabled && this . _bottom !== prevState . bottom ) {
216+ this . setState ( { bottom : this . _bottom } ) ;
217+ }
218+ }
219+
187220 componentDidMount ( ) {
188221 this . _appStateSubscription = AppState . addEventListener ( 'change' , this . _handleAppStateChange ) ;
189222 this . setKeyboardListeners ( ) ;
0 commit comments