diff --git a/src/components/Search/DeferredSearchAutocompleteList/index.native.tsx b/src/components/Search/DeferredSearchAutocompleteList/index.native.tsx new file mode 100644 index 0000000000000..0d0f8771b60ac --- /dev/null +++ b/src/components/Search/DeferredSearchAutocompleteList/index.native.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import OptionsListSkeletonView from '@components/OptionsListSkeletonView'; +import type {SearchAutocompleteListProps} from '@components/Search/SearchAutocompleteList'; +import SearchAutocompleteList from '@components/Search/SearchAutocompleteList'; +import Navigation from '@navigation/Navigation'; +import CONST from '@src/CONST'; + +/** + * This component acts as a wrapper for a SearchAutocompleteList, waiting for the navigation to be ready and deferring it, + * so that the base UI can render before the list is loaded. + * This enables the SearchRouterPage to open smoothly with a placeholder and load the list in the meantime. + */ +function DeferredAutocompleteList(props: SearchAutocompleteListProps) { + const [shouldRender, setShouldRender] = React.useState(false); + + React.useEffect(() => { + Navigation.setNavigationActionToMicrotaskQueue(() => { + setShouldRender(true); + }); + }, []); + + if (!shouldRender) { + return ( + + ); + } + + // eslint-disable-next-line react/jsx-props-no-spreading + return ; +} + +DeferredAutocompleteList.displayName = 'DeferredSearchAutocompleteList'; + +export default DeferredAutocompleteList; diff --git a/src/components/Search/DeferredSearchAutocompleteList/index.tsx b/src/components/Search/DeferredSearchAutocompleteList/index.tsx new file mode 100644 index 0000000000000..bf37646cf0a30 --- /dev/null +++ b/src/components/Search/DeferredSearchAutocompleteList/index.tsx @@ -0,0 +1,6 @@ +/** + * The rendering is fast enough for the web, so only a native implementation is required. See index.native.ts. + */ +import SearchAutocompleteList from '@components/Search/SearchAutocompleteList'; + +export default SearchAutocompleteList; diff --git a/src/components/Search/SearchAutocompleteList.tsx b/src/components/Search/SearchAutocompleteList.tsx index 9a913a37bc94f..bf9dd1c307f23 100644 --- a/src/components/Search/SearchAutocompleteList.tsx +++ b/src/components/Search/SearchAutocompleteList.tsx @@ -4,7 +4,6 @@ import type {ForwardedRef, RefObject} from 'react'; import React, {useEffect, useRef, useState} from 'react'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import {useOptionsList} from '@components/OptionListContextProvider'; -import OptionsListSkeletonView from '@components/OptionsListSkeletonView'; import type {AnimatedTextInputRef} from '@components/RNTextInput'; import type {ListItem as NewListItem, UserListItemProps} from '@components/SelectionList/ListItem/types'; import UserListItem from '@components/SelectionList/ListItem/UserListItem'; @@ -917,16 +916,6 @@ function SearchAutocompleteList({ const isRecentSearchesDataLoaded = !isLoadingOnyxValue(recentSearchesMetadata); const isLoading = !isRecentSearchesDataLoaded || !areOptionsInitialized; - if (isLoading) { - return ( - - ); - } - return ( showLoadingPlaceholder @@ -943,6 +932,7 @@ function SearchAutocompleteList({ shouldSingleExecuteRowSelect ref={setListRef} initialScrollIndex={0} + isLoadingNewOptions={isLoading} initiallyFocusedItemKey={!shouldUseNarrowLayout ? firstRecentReportKey : undefined} shouldScrollToFocusedIndex={!isInitialRender} disableKeyboardShortcuts={!shouldSubscribeToArrowKeyEvents} @@ -960,4 +950,4 @@ SearchAutocompleteList.displayName = 'SearchAutocompleteList'; export default React.memo(SearchAutocompleteList); export {SearchRouterItem}; -export type {GetAdditionalSectionsCallback}; +export type {GetAdditionalSectionsCallback, SearchAutocompleteListProps}; diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index c9a262b3a2230..019ba2bb43a57 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -6,8 +6,8 @@ import type {ValueOf} from 'type-fest'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {usePersonalDetails} from '@components/OnyxListItemProvider'; import type {AnimatedTextInputRef} from '@components/RNTextInput'; +import DeferredAutocompleteList from '@components/Search/DeferredSearchAutocompleteList'; import type {GetAdditionalSectionsCallback} from '@components/Search/SearchAutocompleteList'; -import SearchAutocompleteList from '@components/Search/SearchAutocompleteList'; import {useSearchActionsContext} from '@components/Search/SearchContext'; import SearchInputSelectionWrapper from '@components/Search/SearchInputSelectionWrapper'; import type {SearchQueryString} from '@components/Search/types'; @@ -455,7 +455,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla shouldDelayFocus /> -