diff --git a/src/CONST.ts b/src/CONST.ts index 219807587a25..45b69c952339 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -704,7 +704,7 @@ const CONST = { TOOLTIP_SENSE: 1000, TRIE_INITIALIZATION: 'trie_initialization', COMMENT_LENGTH_DEBOUNCE_TIME: 500, - SEARCH_FOR_REPORTS_DEBOUNCE_TIME: 300, + SEARCH_OPTION_LIST_DEBOUNCE_TIME: 300, }, PRIORITY_MODE: { GSD: 'gsd', diff --git a/src/components/CategoryPicker/index.js b/src/components/CategoryPicker/index.js index d170def12276..a957e31a9de4 100644 --- a/src/components/CategoryPicker/index.js +++ b/src/components/CategoryPicker/index.js @@ -62,7 +62,6 @@ function CategoryPicker({selectedCategory, policyCategories, policyRecentlyUsedC sectionHeaderStyle={styles.mt5} sections={sections} selectedOptions={selectedOptions} - value={searchValue} // Focus the first option when searching focusedIndex={0} // Focus the selected option on first load diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index fc3e4b095873..63181e4aea87 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -565,7 +565,6 @@ function MoneyRequestConfirmationList(props) { return ( { // If we just toggled an option on a multi-selection page or cleared the search input, scroll to top - if (this.props.selectedOptions.length !== prevProps.selectedOptions.length || (!!prevProps.value && !this.props.value)) { + if (this.props.selectedOptions.length !== prevProps.selectedOptions.length || (!!prevState.value && !this.state.value)) { this.scrollToIndex(0); return; } @@ -247,6 +249,7 @@ class BaseOptionsSelector extends Component { this.setState({ paginationPage: 1, errorMessage: value.length > this.props.maxLength ? this.props.translate('common.error.characterLimitExceedCounter', {length: value.length, limit: this.props.maxLength}) : '', + value, }); this.props.onChangeText(value); @@ -415,7 +418,7 @@ class BaseOptionsSelector extends Component { this.relatedTarget = null; } if (this.textInput.isFocused()) { - setSelection(this.textInput, 0, this.props.value.length); + setSelection(this.textInput, 0, this.state.value.length); } } const selectedOption = this.props.onSelectRow(option); @@ -440,7 +443,7 @@ class BaseOptionsSelector extends Component { if (this.props.shouldShowTextInput && this.props.shouldPreventDefaultFocusOnSelectRow) { this.textInput.focus(); if (this.textInput.isFocused()) { - setSelection(this.textInput, 0, this.props.value.length); + setSelection(this.textInput, 0, this.state.value.length); } } this.props.onAddToSelection(option); @@ -468,11 +471,10 @@ class BaseOptionsSelector extends Component { const textInput = ( (this.textInput = el)} - value={this.props.value} label={this.props.textInputLabel} accessibilityLabel={this.props.textInputLabel} role={CONST.ROLE.PRESENTATION} - onChangeText={this.updateSearchValue} + onChangeText={this.debouncedUpdateSearchValue} errorText={this.state.errorMessage} onSubmitEditing={this.selectFocusedOption} placeholder={this.props.placeholderText} diff --git a/src/components/OptionsSelector/optionsSelectorPropTypes.js b/src/components/OptionsSelector/optionsSelectorPropTypes.js index 8593569dfafd..e52187fa76d7 100644 --- a/src/components/OptionsSelector/optionsSelectorPropTypes.js +++ b/src/components/OptionsSelector/optionsSelectorPropTypes.js @@ -27,9 +27,6 @@ const propTypes = { }), ).isRequired, - /** Value in the search input field */ - value: PropTypes.string.isRequired, - /** Callback fired when text changes */ onChangeText: PropTypes.func, diff --git a/src/components/TagPicker/index.js b/src/components/TagPicker/index.js index cb3d9bf260e6..e258472eae93 100644 --- a/src/components/TagPicker/index.js +++ b/src/components/TagPicker/index.js @@ -70,7 +70,6 @@ function TagPicker({selectedTag, tag, policyTags, policyRecentlyUsedTags, should highlightSelectedOptions isRowMultilineSupported shouldShowTextInput={shouldShowTextInput} - value={searchValue} // Focus the first option when searching focusedIndex={0} // Focus the selected option on first load diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 135e616f7691..c3b1532b4d87 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -1,7 +1,6 @@ import {format as timezoneFormat, utcToZonedTime} from 'date-fns-tz'; import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import Str from 'expensify-common/lib/str'; -import lodashDebounce from 'lodash/debounce'; import isEmpty from 'lodash/isEmpty'; import {DeviceEventEmitter, InteractionManager} from 'react-native'; import Onyx, {OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; @@ -2499,8 +2498,6 @@ function searchForReports(searchInput: string) { API.read('SearchForReports', parameters, {successData, failureData}); } -const debouncedSearchInServer = lodashDebounce(searchForReports, CONST.TIMING.SEARCH_FOR_REPORTS_DEBOUNCE_TIME, {leading: false}); - function searchInServer(searchInput: string) { if (isNetworkOffline || !searchInput.trim().length) { Onyx.set(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, false); @@ -2511,7 +2508,7 @@ function searchInServer(searchInput: string) { // we want to show the loading state right away. Otherwise, we will see a flashing UI where the client options are sorted and // tell the user there are no options, then we start searching, and tell them there are no options again. Onyx.set(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, true); - debouncedSearchInServer(searchInput); + searchForReports(searchInput); } function clearNewRoomFormError() { diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 6f45c0b33f5a..d7abbab6e93f 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -244,7 +244,6 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i onAddToSelection={(option) => toggleOption(option)} sections={sections} selectedOptions={selectedOptions} - value={searchTerm} onSelectRow={(option) => createChat(option)} onChangeText={setSearchTermAndSearchInServer} headerMessage={headerMessage} diff --git a/src/pages/SearchPage.js b/src/pages/SearchPage.js index 01fe83289d71..28718d9aac1c 100755 --- a/src/pages/SearchPage.js +++ b/src/pages/SearchPage.js @@ -67,7 +67,6 @@ class SearchPage extends Component { this.selectReport = this.selectReport.bind(this); this.onChangeText = this.onChangeText.bind(this); this.updateOptions = this.updateOptions.bind(this); - this.debouncedUpdateOptions = _.debounce(this.updateOptions.bind(this), 75); this.state = { searchValue: '', recentReports: {}, @@ -85,7 +84,7 @@ class SearchPage extends Component { onChangeText(searchValue = '') { Report.searchInServer(searchValue); - this.setState({searchValue}, this.debouncedUpdateOptions); + this.setState({searchValue}, this.updateOptions); } /** @@ -156,14 +155,7 @@ class SearchPage extends Component { } if (option.reportID) { - this.setState( - { - searchValue: '', - }, - () => { - Navigation.dismissModal(option.reportID); - }, - ); + Navigation.dismissModal(option.reportID); } else { Report.navigateToAndOpenReport([option.login]); } @@ -190,7 +182,6 @@ class SearchPage extends Component { { - onAddParticipants( - [{accountID: option.accountID, login: option.login, isPolicyExpenseChat: option.isPolicyExpenseChat, reportID: option.reportID, selected: true, searchText: option.searchText}], - false, - ); - navigateToRequest(); - }; + const addSingleParticipant = useCallback( + (option) => { + onAddParticipants( + [ + { + accountID: option.accountID, + login: option.login, + isPolicyExpenseChat: option.isPolicyExpenseChat, + reportID: option.reportID, + selected: true, + searchText: option.searchText, + }, + ], + false, + ); + navigateToRequest(); + }, + [onAddParticipants, navigateToRequest], + ); /** * Removes a selected option from list if already selected. If not already selected add this option to the list. @@ -215,12 +222,16 @@ function MoneyRequestParticipantsSelector({ [participants, onAddParticipants], ); - const headerMessage = OptionsListUtils.getHeaderMessage( - newChatOptions.personalDetails.length + newChatOptions.recentReports.length !== 0, - Boolean(newChatOptions.userToInvite), - searchTerm.trim(), - maxParticipantsReached, - _.some(participants, (participant) => participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase())), + const headerMessage = useMemo( + () => + OptionsListUtils.getHeaderMessage( + newChatOptions.personalDetails.length + newChatOptions.recentReports.length !== 0, + Boolean(newChatOptions.userToInvite), + searchTerm.trim(), + maxParticipantsReached, + _.some(participants, (participant) => participant.searchText.toLowerCase().includes(searchTerm.trim().toLowerCase())), + ), + [maxParticipantsReached, newChatOptions.personalDetails.length, newChatOptions.recentReports.length, newChatOptions.userToInvite, participants, searchTerm], ); const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(personalDetails); @@ -278,23 +289,27 @@ function MoneyRequestParticipantsSelector({ navigateToSplit(); }, [shouldShowSplitBillErrorMessage, navigateToSplit]); - const footerContent = ( - - {shouldShowSplitBillErrorMessage && ( - ( + + {shouldShowSplitBillErrorMessage && ( + + )} +