diff --git a/src/components/MagicCodeInput.js b/src/components/MagicCodeInput.js index cea98cfd3747..dd1c93d9280a 100644 --- a/src/components/MagicCodeInput.js +++ b/src/components/MagicCodeInput.js @@ -27,9 +27,6 @@ const propTypes = { /** Should the input auto focus */ autoFocus: PropTypes.bool, - /** Whether we should wait before focusing the TextInput, useful when using transitions */ - shouldDelayFocus: PropTypes.bool, - /** Error text to display */ errorText: PropTypes.string, @@ -58,7 +55,6 @@ const defaultProps = { value: undefined, name: '', autoFocus: true, - shouldDelayFocus: false, errorText: '', shouldSubmitOnComplete: true, innerRef: null, @@ -141,28 +137,6 @@ function MagicCodeInput(props) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.value, props.shouldSubmitOnComplete]); - useEffect(() => { - if (!props.autoFocus) { - return; - } - - let focusTimeout = null; - if (props.shouldDelayFocus) { - focusTimeout = setTimeout(() => inputRefs.current[0].focus(), CONST.ANIMATED_TRANSITION); - } else { - inputRefs.current[0].focus(); - } - - return () => { - if (!focusTimeout) { - return; - } - clearTimeout(focusTimeout); - }; - // We only want this to run on mount - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - /** * Callback for the onFocus event, updates the indexes * of the currently focused input. @@ -290,7 +264,7 @@ function MagicCodeInput(props) { (inputRefs.current[index] = ref)} - autoFocus={index === 0 && props.autoFocus && !props.shouldDelayFocus} + autoFocus={index === 0 && props.autoFocus} inputMode="numeric" textContentType="oneTimeCode" name={props.name} diff --git a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js index 2289e68e7bd1..7b2cf85ef141 100644 --- a/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js +++ b/src/pages/settings/Profile/Contacts/ContactMethodDetailsPage.js @@ -103,6 +103,8 @@ class ContactMethodDetailsPage extends Component { this.state = { isDeleteModalOpen: false, }; + + this.validateCodeFormRef = React.createRef(); } componentDidMount() { @@ -217,7 +219,7 @@ class ContactMethodDetailsPage extends Component { const isFailedAddContactMethod = Boolean(lodashGet(loginData, 'errorFields.addedLogin')); return ( - + this.validateCodeFormRef.current && this.validateCodeFormRef.current.focus()}> Navigation.goBack(ROUTES.SETTINGS_CONTACT_METHODS)} @@ -251,6 +253,7 @@ class ContactMethodDetailsPage extends Component { contactMethod={contactMethod} hasMagicCodeBeenSent={hasMagicCodeBeenSent} loginList={this.props.loginList} + ref={this.validateCodeFormRef} /> )} diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js index ea81413fcbb5..578e4dc3a2f6 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/BaseValidateCodeForm.js @@ -1,4 +1,4 @@ -import React, {useCallback, useState, useEffect, useRef} from 'react'; +import React, {useCallback, useState, useEffect, useRef, useImperativeHandle} from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; @@ -16,7 +16,6 @@ import * as User from '../../../../../libs/actions/User'; import Button from '../../../../../components/Button'; import DotIndicatorMessage from '../../../../../components/DotIndicatorMessage'; import * as Session from '../../../../../libs/actions/Session'; -import shouldDelayFocus from '../../../../../libs/shouldDelayFocus'; import Text from '../../../../../components/Text'; import {withNetwork} from '../../../../../components/OnyxProvider'; import PressableWithFeedback from '../../../../../components/Pressable/PressableWithFeedback'; @@ -51,6 +50,9 @@ const propTypes = { pendingFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)), }).isRequired, + /** Forwarded inner ref */ + innerRef: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + /* Onyx Props */ /** The details about the account that the user is signing in with */ @@ -65,6 +67,7 @@ const propTypes = { const defaultProps = { account: {}, + innerRef: () => {}, }; function BaseValidateCodeForm(props) { @@ -74,6 +77,15 @@ function BaseValidateCodeForm(props) { const inputValidateCodeRef = useRef(); const validateLoginError = ErrorUtils.getEarliestErrorField(loginData, 'validateLogin'); + useImperativeHandle(props.innerRef, () => ({ + focus() { + if (!inputValidateCodeRef.current) { + return; + } + inputValidateCodeRef.current.focus(); + }, + })); + useEffect(() => { if (!props.hasMagicCodeBeenSent) { return; @@ -138,8 +150,7 @@ function BaseValidateCodeForm(props) { errorText={formError.validateCode ? props.translate(formError.validateCode) : ErrorUtils.getLatestErrorMessage(props.account)} hasError={!_.isEmpty(validateLoginError)} onFulfill={validateAndSubmitForm} - autoFocus - shouldDelayFocus={shouldDelayFocus} + autoFocus={false} /> - ); -} +const ValidateCodeForm = forwardRef((props, ref) => ( + +)); ValidateCodeForm.displayName = 'ValidateCodeForm'; diff --git a/src/pages/settings/Profile/Contacts/ValidateCodeForm/index.js b/src/pages/settings/Profile/Contacts/ValidateCodeForm/index.js index 6ef0c91b6d37..bb4e5ed36b47 100644 --- a/src/pages/settings/Profile/Contacts/ValidateCodeForm/index.js +++ b/src/pages/settings/Profile/Contacts/ValidateCodeForm/index.js @@ -1,15 +1,14 @@ -import React from 'react'; +import React, {forwardRef} from 'react'; import BaseValidateCodeForm from './BaseValidateCodeForm'; -function ValidateCodeForm(props) { - return ( - - ); -} +const ValidateCodeForm = forwardRef((props, ref) => ( + +)); ValidateCodeForm.displayName = 'ValidateCodeForm'; diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js index 7455a19f1131..4c0bf81210b4 100644 --- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js +++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/BaseTwoFactorAuthForm.js @@ -75,6 +75,12 @@ function BaseTwoFactorAuthForm(props) { validateAndSubmitForm() { validateAndSubmitForm(); }, + focus() { + if (!inputRef.current) { + return; + } + inputRef.current.focus(); + }, })); return ( @@ -89,6 +95,7 @@ function BaseTwoFactorAuthForm(props) { onFulfill={validateAndSubmitForm} errorText={formError.twoFactorAuthCode ? props.translate(formError.twoFactorAuthCode) : ErrorUtils.getLatestErrorMessage(props.account)} ref={inputRef} + autoFocus={false} /> ); } diff --git a/src/pages/settings/Security/TwoFactorAuth/VerifyPage.js b/src/pages/settings/Security/TwoFactorAuth/VerifyPage.js index 502d48a919d2..e67f0469db62 100644 --- a/src/pages/settings/Security/TwoFactorAuth/VerifyPage.js +++ b/src/pages/settings/Security/TwoFactorAuth/VerifyPage.js @@ -93,7 +93,10 @@ function VerifyPage(props) { } return ( - + formRef.current && formRef.current.focus()} + >