diff --git a/src/hooks/useAutoFocusInput.js b/src/hooks/useAutoFocusInput.js new file mode 100644 index 000000000000..6611f867f210 --- /dev/null +++ b/src/hooks/useAutoFocusInput.js @@ -0,0 +1,40 @@ +import {useFocusEffect} from '@react-navigation/native'; +import {useState, useEffect, useRef, useCallback} from 'react'; +import CONST from '../CONST'; + +export default function useAutoFocusInput() { + const [isInputInitialized, setIsInputInitialized] = useState(false); + const [isScreenTransitionEnded, setIsScreenTransitionEnded] = useState(false); + + const inputRef = useRef(null); + const focusTimeoutRef = useRef(null); + + useEffect(() => { + if (!isScreenTransitionEnded || !isInputInitialized || !inputRef.current) { + return; + } + inputRef.current.focus(); + }, [isScreenTransitionEnded, isInputInitialized]); + + useFocusEffect( + useCallback(() => { + focusTimeoutRef.current = setTimeout(() => { + setIsScreenTransitionEnded(true); + }, CONST.ANIMATED_TRANSITION); + return () => { + if (!focusTimeoutRef.current) { + return; + } + clearTimeout(focusTimeoutRef.current); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []), + ); + + const inputCallbackRef = (ref) => { + inputRef.current = ref; + setIsInputInitialized(true); + }; + + return {inputCallbackRef}; +} diff --git a/src/pages/tasks/NewTaskDetailsPage.js b/src/pages/tasks/NewTaskDetailsPage.js index b7fd3900e1f3..668a61526198 100644 --- a/src/pages/tasks/NewTaskDetailsPage.js +++ b/src/pages/tasks/NewTaskDetailsPage.js @@ -1,4 +1,4 @@ -import React, {useEffect, useRef, useState} from 'react'; +import React, {useEffect, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; @@ -17,6 +17,7 @@ import ROUTES from '../../ROUTES'; import * as Task from '../../libs/actions/Task'; import CONST from '../../CONST'; import * as Browser from '../../libs/Browser'; +import useAutoFocusInput from '../../hooks/useAutoFocusInput'; const propTypes = { /** Beta features list */ @@ -37,10 +38,11 @@ const defaultProps = { }; function NewTaskDetailsPage(props) { - const inputRef = useRef(); const [taskTitle, setTaskTitle] = useState(props.task.title); const [taskDescription, setTaskDescription] = useState(props.task.description || ''); + const {inputCallbackRef} = useAutoFocusInput(); + useEffect(() => { setTaskTitle(props.task.title); setTaskDescription(props.task.description || ''); @@ -74,7 +76,6 @@ function NewTaskDetailsPage(props) { } return ( inputRef.current && inputRef.current.focus()} includeSafeAreaPaddingBottom={false} shouldEnableMaxHeight testID={NewTaskDetailsPage.displayName} @@ -95,7 +96,7 @@ function NewTaskDetailsPage(props) { > (inputRef.current = el)} + ref={inputCallbackRef} accessibilityRole={CONST.ACCESSIBILITY_ROLE.TEXT} inputID="taskTitle" label={props.translate('task.title')}