diff --git a/src/components/DatePicker/index.android.js b/src/components/DatePicker/index.android.js index 561fc700b6a..587439208fe 100644 --- a/src/components/DatePicker/index.android.js +++ b/src/components/DatePicker/index.android.js @@ -7,7 +7,7 @@ import styles from '@styles/styles'; import CONST from '@src/CONST'; import {defaultProps, propTypes} from './datepickerPropTypes'; -function DatePicker({value, defaultValue, label, placeholder, errorText, containerStyles, disabled, onBlur, onInputChange, maxDate, minDate}, outerRef) { +const DatePicker = forwardRef(({value, defaultValue, label, placeholder, errorText, containerStyles, disabled, onBlur, onInputChange, maxDate, minDate}, outerRef) => { const ref = useRef(); const [isPickerVisible, setIsPickerVisible] = useState(false); @@ -70,10 +70,10 @@ function DatePicker({value, defaultValue, label, placeholder, errorText, contain )} ); -} +}); DatePicker.propTypes = propTypes; DatePicker.defaultProps = defaultProps; DatePicker.displayName = 'DatePicker'; -export default forwardRef(DatePicker); +export default DatePicker; diff --git a/src/components/ScreenWrapper/index.js b/src/components/ScreenWrapper/index.js index 075cae568cf..f9173c15da7 100644 --- a/src/components/ScreenWrapper/index.js +++ b/src/components/ScreenWrapper/index.js @@ -21,149 +21,155 @@ import toggleTestToolsModal from '@userActions/TestTool'; import CONST from '@src/CONST'; import {defaultProps, propTypes} from './propTypes'; -function ScreenWrapper({ - shouldEnableMaxHeight, - shouldEnableMinHeight, - includePaddingTop, - keyboardAvoidingViewBehavior, - includeSafeAreaPaddingBottom, - shouldEnableKeyboardAvoidingView, - shouldEnablePickerAvoiding, - headerGapStyles, - children, - shouldShowOfflineIndicator, - offlineIndicatorStyle, - style, - shouldDismissKeyboardBeforeClose, - onEntryTransitionEnd, - testID, -}) { - const {windowHeight, isSmallScreenWidth} = useWindowDimensions(); - const {initialHeight} = useInitialDimensions(); - const keyboardState = useKeyboardState(); - const {isDevelopment} = useEnvironment(); - const {isOffline} = useNetwork(); - const navigation = useNavigation(); - const [didScreenTransitionEnd, setDidScreenTransitionEnd] = useState(false); - const maxHeight = shouldEnableMaxHeight ? windowHeight : undefined; - const minHeight = shouldEnableMinHeight ? initialHeight : undefined; - const isKeyboardShown = lodashGet(keyboardState, 'isKeyboardShown', false); - - const isKeyboardShownRef = useRef(); - - isKeyboardShownRef.current = lodashGet(keyboardState, 'isKeyboardShown', false); - - const panResponder = useRef( - PanResponder.create({ - onStartShouldSetPanResponderCapture: (e, gestureState) => gestureState.numberActiveTouches === CONST.TEST_TOOL.NUMBER_OF_TAPS, - onPanResponderRelease: toggleTestToolsModal, - }), - ).current; - - const keyboardDissmissPanResponder = useRef( - PanResponder.create({ - onMoveShouldSetPanResponderCapture: (e, gestureState) => { - const isHorizontalSwipe = Math.abs(gestureState.dx) > Math.abs(gestureState.dy); - const shouldDismissKeyboard = shouldDismissKeyboardBeforeClose && isKeyboardShown && Browser.isMobile(); - - return isHorizontalSwipe && shouldDismissKeyboard; - }, - onPanResponderGrant: Keyboard.dismiss, - }), - ).current; - - useEffect(() => { - const unsubscribeTransitionEnd = navigation.addListener('transitionEnd', (event) => { - // Prevent firing the prop callback when user is exiting the page. - if (lodashGet(event, 'data.closing')) { - return; - } - - setDidScreenTransitionEnd(true); - onEntryTransitionEnd(); - }); - - // We need to have this prop to remove keyboard before going away from the screen, to avoid previous screen look weird for a brief moment, - // also we need to have generic control in future - to prevent closing keyboard for some rare cases in which beforeRemove has limitations - // described here https://reactnavigation.org/docs/preventing-going-back/#limitations - const beforeRemoveSubscription = shouldDismissKeyboardBeforeClose - ? navigation.addListener('beforeRemove', () => { - if (!isKeyboardShownRef.current) { - return; - } - Keyboard.dismiss(); - }) - : undefined; - - return () => { - unsubscribeTransitionEnd(); - - if (beforeRemoveSubscription) { - beforeRemoveSubscription(); - } - }; - // Rule disabled because this effect is only for component did mount & will component unmount lifecycle event - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return ( - - {({insets, paddingTop, paddingBottom, safeAreaPaddingBottomStyle}) => { - const paddingStyle = {}; - - if (includePaddingTop) { - paddingStyle.paddingTop = paddingTop; +const ScreenWrapper = React.forwardRef( + ( + { + shouldEnableMaxHeight, + shouldEnableMinHeight, + includePaddingTop, + keyboardAvoidingViewBehavior, + includeSafeAreaPaddingBottom, + shouldEnableKeyboardAvoidingView, + shouldEnablePickerAvoiding, + headerGapStyles, + children, + shouldShowOfflineIndicator, + offlineIndicatorStyle, + style, + shouldDismissKeyboardBeforeClose, + onEntryTransitionEnd, + testID, + }, + ref, + ) => { + const {windowHeight, isSmallScreenWidth} = useWindowDimensions(); + const {initialHeight} = useInitialDimensions(); + const keyboardState = useKeyboardState(); + const {isDevelopment} = useEnvironment(); + const {isOffline} = useNetwork(); + const navigation = useNavigation(); + const [didScreenTransitionEnd, setDidScreenTransitionEnd] = useState(false); + const maxHeight = shouldEnableMaxHeight ? windowHeight : undefined; + const minHeight = shouldEnableMinHeight ? initialHeight : undefined; + const isKeyboardShown = lodashGet(keyboardState, 'isKeyboardShown', false); + + const isKeyboardShownRef = useRef(); + + isKeyboardShownRef.current = lodashGet(keyboardState, 'isKeyboardShown', false); + + const panResponder = useRef( + PanResponder.create({ + onStartShouldSetPanResponderCapture: (e, gestureState) => gestureState.numberActiveTouches === CONST.TEST_TOOL.NUMBER_OF_TAPS, + onPanResponderRelease: toggleTestToolsModal, + }), + ).current; + + const keyboardDissmissPanResponder = useRef( + PanResponder.create({ + onMoveShouldSetPanResponderCapture: (e, gestureState) => { + const isHorizontalSwipe = Math.abs(gestureState.dx) > Math.abs(gestureState.dy); + const shouldDismissKeyboard = shouldDismissKeyboardBeforeClose && isKeyboardShown && Browser.isMobile(); + + return isHorizontalSwipe && shouldDismissKeyboard; + }, + onPanResponderGrant: Keyboard.dismiss, + }), + ).current; + + useEffect(() => { + const unsubscribeTransitionEnd = navigation.addListener('transitionEnd', (event) => { + // Prevent firing the prop callback when user is exiting the page. + if (lodashGet(event, 'data.closing')) { + return; } - // We always need the safe area padding bottom if we're showing the offline indicator since it is bottom-docked. - if (includeSafeAreaPaddingBottom || (isOffline && shouldShowOfflineIndicator)) { - paddingStyle.paddingBottom = paddingBottom; + setDidScreenTransitionEnd(true); + onEntryTransitionEnd(); + }); + + // We need to have this prop to remove keyboard before going away from the screen, to avoid previous screen look weird for a brief moment, + // also we need to have generic control in future - to prevent closing keyboard for some rare cases in which beforeRemove has limitations + // described here https://reactnavigation.org/docs/preventing-going-back/#limitations + const beforeRemoveSubscription = shouldDismissKeyboardBeforeClose + ? navigation.addListener('beforeRemove', () => { + if (!isKeyboardShownRef.current) { + return; + } + Keyboard.dismiss(); + }) + : undefined; + + return () => { + unsubscribeTransitionEnd(); + + if (beforeRemoveSubscription) { + beforeRemoveSubscription(); } - - return ( - + }; + // Rule disabled because this effect is only for component did mount & will component unmount lifecycle event + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( + + {({insets, paddingTop, paddingBottom, safeAreaPaddingBottomStyle}) => { + const paddingStyle = {}; + + if (includePaddingTop) { + paddingStyle.paddingTop = paddingTop; + } + + // We always need the safe area padding bottom if we're showing the offline indicator since it is bottom-docked. + if (includeSafeAreaPaddingBottom || (isOffline && shouldShowOfflineIndicator)) { + paddingStyle.paddingBottom = paddingBottom; + } + + return ( - - - - {isDevelopment && } - {isDevelopment && } - { - // If props.children is a function, call it to provide the insets to the children. - _.isFunction(children) - ? children({ - insets, - safeAreaPaddingBottomStyle, - didScreenTransitionEnd, - }) - : children - } - {isSmallScreenWidth && shouldShowOfflineIndicator && } - - + + + {isDevelopment && } + {isDevelopment && } + { + // If props.children is a function, call it to provide the insets to the children. + _.isFunction(children) + ? children({ + insets, + safeAreaPaddingBottomStyle, + didScreenTransitionEnd, + }) + : children + } + {isSmallScreenWidth && shouldShowOfflineIndicator && } + + + - - ); - }} - - ); -} + ); + }} + + ); + }, +); ScreenWrapper.displayName = 'ScreenWrapper'; ScreenWrapper.propTypes = propTypes; diff --git a/src/pages/ReimbursementAccount/RequestorStep.js b/src/pages/ReimbursementAccount/RequestorStep.js index 0eddb727d56..4a3dd2f0917 100644 --- a/src/pages/ReimbursementAccount/RequestorStep.js +++ b/src/pages/ReimbursementAccount/RequestorStep.js @@ -70,7 +70,11 @@ const validate = (values) => { return errors; }; -function RequestorStep({reimbursementAccount, shouldShowOnfido, onBackButtonPress, getDefaultStateForField}) { +/** + * Workaround for forwardRef + propTypes issue. + * See https://stackoverflow.com/questions/59716140/using-forwardref-with-proptypes-and-eslint + */ +const RequestorStep = React.forwardRef(({reimbursementAccount, shouldShowOnfido, onBackButtonPress, getDefaultStateForField}, ref) => { const {translate} = useLocalize(); const defaultValues = useMemo( @@ -108,6 +112,7 @@ function RequestorStep({reimbursementAccount, shouldShowOnfido, onBackButtonPres if (shouldShowOnfido) { return ( @@ -116,6 +121,7 @@ function RequestorStep({reimbursementAccount, shouldShowOnfido, onBackButtonPres return ( @@ -190,9 +196,9 @@ function RequestorStep({reimbursementAccount, shouldShowOnfido, onBackButtonPres ); -} +}); RequestorStep.propTypes = propTypes; RequestorStep.displayName = 'RequestorStep'; -export default React.forwardRef(RequestorStep); +export default RequestorStep;