이전 프로젝트를 찾아보며 기록할 때마다 느끼는 것이지만, 왜 이전에는 기록해두지 않았을까... 하는 생각밖에 안드는데, 뭐 지금부터라도 기록해야지 어쩌겠는가.
가끔씩, react native 자체나 서드파티에서 알 수 없는 문제를 발견할 때가 있다.
두 가지 운영체제를 지원하는데다, 두 가지 운영체제 모두 서로 다른 다양한 기능을 하나의 JS코드로 지원하다보니 생기는 문제가 대부분이다. 그럴 때에 patch-package로 문제를 해결했던 경험을 정리해본다.
https://github.com/facebook/react-native/issues/29974
참고:
당시 프로젝트의 RN 버전은 0.63.4 이며, 현재 React-Native 프레임워크는 패치 코드가 적용된 채로 업데이트되었습니다.
KeyboardavoidingView란 react-native에서 맨 상위 view 아래 선언해, 버츄얼 키보드가 동작할 경우 behavior prop의 padding, height, position에 맞게 View 자체의 크기를 애니메이션 효과와 함께 조정해 주는 RN 빌트인 엘리먼트이다.
문제는 ios 14 업데이트 이후 추가된 동작 줄이기에서 "크로스페이드 전환 설정"을 킬 경우, ios에서 KeyboardavoidingView로 감싸진 코드 전체가 사라지는 현상이 일어났다는 것이다.
해당 깃헙에서 문제 자체는 빠르게 해결할 수 있었다.
diff --git a/node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js b/node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js
index 7c794ea..e3881ed 100644
--- a/node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js
+++ b/node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js
@@ -79,7 +79,9 @@ class KeyboardAvoidingView extends React.Component<Props, State> {
_relativeKeyboardHeight(keyboardFrame): number {
const frame = this._frame;
- if (!frame || !keyboardFrame) {
+ // with iOS 14 & Reduce Motion > Prefer Cross-Fade Transitions enabled, the keyboard position
+ // & height is reported differently (0 instead of Y position value matching height of frame)
+ if (!frame || !keyboardFrame || keyboardFrame.screenY === 0) {
return 0;
}
ios에서 상술한 옵션을 적용할 경우, keyboardFrame 객체 인자가 제대로 들어오지 않는 문제인 것으로 확인하였다. 정확한 문제(Native단)는 아래 깃헙 링크에서 확인해 보았을 때 아직 해결 중인것으로 보인다.
KeyboardAvoidingView(ios)가 어떻게 동작하는지부터 살펴보면,
// react-native/React/CoreModules/RCTKeyboardObserver.mm
static NSDictionary *RCTParseKeyboardNotification(NSNotification *notification)
{
NSDictionary *userInfo = notification.userInfo;
CGRect beginFrame = [userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGRect endFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve =
static_cast<UIViewAnimationCurve>([userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]);
NSInteger isLocalUserInfoKey = [userInfo[UIKeyboardIsLocalUserInfoKey] integerValue];
return @{
@"startCoordinates" : RCTRectDictionaryValue(beginFrame),
@"endCoordinates" : RCTRectDictionaryValue(endFrame), // RN에서는 요 부분을 가져와서, 키보드의 hieght를 측정한다!
@"duration" : @(duration * 1000.0), // ms
@"easing" : RCTAnimationNameForCurve(curve),
@"isEventFromThisApp" : isLocalUserInfoKey == 1 ? @YES : @NO,
};
}
Class RCTKeyboardObserverCls(void)
{
return RCTKeyboardObserver.class;
}
_relativeKeyboardHeight(keyboardFrame): number {
const frame = this._frame;
if (!frame || !keyboardFrame ) { // 이부분이 문제가 되어 0이 리턴이 된다!
return 0;
}
RN 자체의 KeyboardAvoidingView.js를 확인해 보면, 이처럼 ios의 Keyboard
위 패치는 patch-package에서 자체적으로 생성해 준 것으로 아래 순서대로 적용한다.
아래 내용대로 KeyboardAvoidingView의 문제를 해결할 수 있었다.
지금은 RN 코드 자체에 패치가 적용되어있어 이것을 적용할 필요는 없지만, 추후 이러한 문제는 언제든 생길 수 있으므로 적어두는 것이 좋다고 생각한다.
참고한 url