diff --git a/src/pages/RoomInvitePage.js b/src/pages/RoomInvitePage.js index b3de1eb53548..3f55ad6c0ff7 100644 --- a/src/pages/RoomInvitePage.js +++ b/src/pages/RoomInvitePage.js @@ -1,3 +1,4 @@ +import {useNavigation} from '@react-navigation/native'; import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; @@ -71,6 +72,8 @@ function RoomInvitePage(props) { const [selectedOptions, setSelectedOptions] = useState([]); const [personalDetails, setPersonalDetails] = useState([]); const [userToInvite, setUserToInvite] = useState(null); + const [didScreenTransitionEnd, setDidScreenTransitionEnd] = useState(false); + const navigation = useNavigation(); // Any existing participants and Expensify emails should not be eligible for invitation const excludedUsers = useMemo( @@ -95,10 +98,26 @@ function RoomInvitePage(props) { // eslint-disable-next-line react-hooks/exhaustive-deps -- we don't want to recalculate when selectedOptions change }, [props.personalDetails, props.betas, searchTerm, excludedUsers]); - const getSections = () => { - const sections = []; + useEffect(() => { + const unsubscribeTransitionEnd = navigation.addListener('transitionEnd', () => { + setDidScreenTransitionEnd(true); + }); + + return () => { + unsubscribeTransitionEnd(); + }; + // Rule disabled because this effect is only for component did mount & will component unmount lifecycle event + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const sections = useMemo(() => { + const sectionsArr = []; let indexOffset = 0; + if (!didScreenTransitionEnd) { + return []; + } + // Filter all options that is a part of the search term or in the personal details let filterSelectedOptions = selectedOptions; if (searchTerm !== '') { @@ -112,7 +131,7 @@ function RoomInvitePage(props) { }); } - sections.push({ + sectionsArr.push({ title: undefined, data: filterSelectedOptions, shouldShow: true, @@ -126,7 +145,7 @@ function RoomInvitePage(props) { const personalDetailsFormatted = _.map(personalDetailsWithoutSelected, (personalDetail) => OptionsListUtils.formatMemberForList(personalDetail, false)); const hasUnselectedUserToInvite = userToInvite && !_.contains(selectedLogins, userToInvite.login); - sections.push({ + sectionsArr.push({ title: translate('common.contacts'), data: personalDetailsFormatted, shouldShow: !_.isEmpty(personalDetailsFormatted), @@ -135,7 +154,7 @@ function RoomInvitePage(props) { indexOffset += personalDetailsFormatted.length; if (hasUnselectedUserToInvite) { - sections.push({ + sectionsArr.push({ title: undefined, data: [OptionsListUtils.formatMemberForList(userToInvite, false)], shouldShow: true, @@ -143,8 +162,8 @@ function RoomInvitePage(props) { }); } - return sections; - }; + return sectionsArr; + }, [personalDetails, searchTerm, selectedOptions, translate, userToInvite, didScreenTransitionEnd]); const toggleOption = useCallback( (option) => { @@ -213,49 +232,43 @@ function RoomInvitePage(props) { shouldEnableMaxHeight testID={RoomInvitePage.displayName} > - {({didScreenTransitionEnd}) => { - const sections = didScreenTransitionEnd ? getSections() : []; - - return ( - Navigation.goBack(backRoute)} - > - { - Navigation.goBack(backRoute); - }} - /> - - - - - - ); - }} + Navigation.goBack(backRoute)} + > + { + Navigation.goBack(backRoute); + }} + /> + + + + + ); } diff --git a/src/pages/workspace/WorkspaceInvitePage.js b/src/pages/workspace/WorkspaceInvitePage.js index 9c831ebda428..72f3747c127c 100644 --- a/src/pages/workspace/WorkspaceInvitePage.js +++ b/src/pages/workspace/WorkspaceInvitePage.js @@ -1,3 +1,4 @@ +import {useNavigation} from '@react-navigation/native'; import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; @@ -76,6 +77,8 @@ function WorkspaceInvitePage(props) { const [selectedOptions, setSelectedOptions] = useState([]); const [personalDetails, setPersonalDetails] = useState([]); const [usersToInvite, setUsersToInvite] = useState([]); + const [didScreenTransitionEnd, setDidScreenTransitionEnd] = useState(false); + const navigation = useNavigation(); const openWorkspaceInvitePage = () => { const policyMemberEmailsToAccountIDs = PolicyUtils.getMemberAccountIDsForWorkspace(props.policyMembers, props.personalDetails); Policy.openWorkspaceInvitePage(props.route.params.policyID, _.keys(policyMemberEmailsToAccountIDs)); @@ -94,6 +97,18 @@ function WorkspaceInvitePage(props) { // eslint-disable-next-line react-hooks/exhaustive-deps -- policyID changes remount the component }, []); + useEffect(() => { + const unsubscribeTransitionEnd = navigation.addListener('transitionEnd', () => { + setDidScreenTransitionEnd(true); + }); + + return () => { + unsubscribeTransitionEnd(); + }; + // Rule disabled because this effect is only for component did mount & will component unmount lifecycle event + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + useNetwork({onReconnect: openWorkspaceInvitePage}); const excludedUsers = useMemo(() => PolicyUtils.getIneligibleInvitees(props.policyMembers, props.personalDetails), [props.policyMembers, props.personalDetails]); @@ -145,10 +160,14 @@ function WorkspaceInvitePage(props) { // eslint-disable-next-line react-hooks/exhaustive-deps -- we don't want to recalculate when selectedOptions change }, [props.personalDetails, props.policyMembers, props.betas, searchTerm, excludedUsers]); - const getSections = () => { - const sections = []; + const sections = useMemo(() => { + const sectionsArr = []; let indexOffset = 0; + if (!didScreenTransitionEnd) { + return []; + } + // Filter all options that is a part of the search term or in the personal details let filterSelectedOptions = selectedOptions; if (searchTerm !== '') { @@ -163,7 +182,7 @@ function WorkspaceInvitePage(props) { }); } - sections.push({ + sectionsArr.push({ title: undefined, data: filterSelectedOptions, shouldShow: true, @@ -176,7 +195,7 @@ function WorkspaceInvitePage(props) { const personalDetailsWithoutSelected = _.filter(personalDetails, ({login}) => !_.contains(selectedLogins, login)); const personalDetailsFormatted = _.map(personalDetailsWithoutSelected, OptionsListUtils.formatMemberForList); - sections.push({ + sectionsArr.push({ title: translate('common.contacts'), data: personalDetailsFormatted, shouldShow: !_.isEmpty(personalDetailsFormatted), @@ -188,7 +207,7 @@ function WorkspaceInvitePage(props) { const hasUnselectedUserToInvite = !_.contains(selectedLogins, userToInvite.login); if (hasUnselectedUserToInvite) { - sections.push({ + sectionsArr.push({ title: undefined, data: [OptionsListUtils.formatMemberForList(userToInvite)], shouldShow: true, @@ -197,8 +216,8 @@ function WorkspaceInvitePage(props) { } }); - return sections; - }; + return sectionsArr; + }, [personalDetails, searchTerm, selectedOptions, usersToInvite, translate, didScreenTransitionEnd]); const toggleOption = (option) => { Policy.clearErrors(props.route.params.policyID); @@ -269,56 +288,50 @@ function WorkspaceInvitePage(props) { shouldEnableMaxHeight testID={WorkspaceInvitePage.displayName} > - {({didScreenTransitionEnd}) => { - const sections = didScreenTransitionEnd ? getSections() : []; - - return ( - Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)} - > - { - Policy.clearErrors(props.route.params.policyID); - Navigation.goBack(ROUTES.WORKSPACE_MEMBERS.getRoute(props.route.params.policyID)); - }} - /> - { - SearchInputManager.searchInput = value; - setSearchTerm(value); - }} - headerMessage={headerMessage} - onSelectRow={toggleOption} - onConfirm={inviteUser} - showScrollIndicator - showLoadingPlaceholder={!didScreenTransitionEnd || !OptionsListUtils.isPersonalDetailsReady(props.personalDetails)} - shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} - /> - - - - - ); - }} + Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)} + > + { + Policy.clearErrors(props.route.params.policyID); + Navigation.goBack(ROUTES.WORKSPACE_MEMBERS.getRoute(props.route.params.policyID)); + }} + /> + { + SearchInputManager.searchInput = value; + setSearchTerm(value); + }} + headerMessage={headerMessage} + onSelectRow={toggleOption} + onConfirm={inviteUser} + showScrollIndicator + showLoadingPlaceholder={!didScreenTransitionEnd || !OptionsListUtils.isPersonalDetailsReady(props.personalDetails)} + shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} + /> + + + + ); }