From c7b9245f49b38fae0dd03962efb84c0ca9c6bfe1 Mon Sep 17 00:00:00 2001 From: Nikhil Vats Date: Mon, 5 Jun 2023 19:28:38 +0530 Subject: [PATCH 1/9] Migrate NewChatPage to functional component --- src/pages/NewChatPage.js | 266 +++++++++++++++++---------------------- 1 file changed, 117 insertions(+), 149 deletions(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 1765c700221e..d241c46415f4 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -1,5 +1,5 @@ import _ from 'underscore'; -import React, {Component} from 'react'; +import React, {useState, useEffect, useMemo} from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; @@ -44,80 +44,57 @@ const defaultProps = { reports: {}, }; -class NewChatPage extends Component { - constructor(props) { - super(props); - - this.toggleOption = this.toggleOption.bind(this); - this.createChat = this.createChat.bind(this); - this.createGroup = this.createGroup.bind(this); - this.updateOptionsWithSearchTerm = this.updateOptionsWithSearchTerm.bind(this); - this.excludedGroupEmails = _.without(CONST.EXPENSIFY_EMAILS, CONST.EMAIL.CONCIERGE); - - const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions( - props.reports, - props.personalDetails, - props.betas, - '', - [], - this.props.isGroupChat ? this.excludedGroupEmails : [], - ); - this.state = { - searchTerm: '', - recentReports, - personalDetails, - selectedOptions: [], - userToInvite, - }; - } - - componentDidUpdate(prevProps) { - if (_.isEqual(prevProps.reports, this.props.reports) && _.isEqual(prevProps.personalDetails, this.props.personalDetails)) { - return; - } - this.updateOptionsWithSearchTerm(this.state.searchTerm); - } - - /** - * Returns the sections needed for the OptionsSelector - * - * @param {Boolean} maxParticipantsReached - * @returns {Array} - */ - getSections(maxParticipantsReached) { - const sections = []; +const NewChatPage = (props) => { + const [searchTerm, setSearchTerm] = useState(''); + const [filteredRecentReports, setFilteredRecentReports] = useState([]); + const [filteredPersonalDetails, setFilteredPersonalDetails] = useState([]); + const [filteredUserToInvite, setFilteredUserToInvite] = useState(); + const [selectedOptions, setSelectedOptions] = useState([]); + + const excludedGroupEmails = _.without(CONST.EXPENSIFY_EMAILS, CONST.EMAIL.CONCIERGE); + const maxParticipantsReached = selectedOptions.length === CONST.REPORT.MAXIMUM_PARTICIPANTS; + const headerMessage = OptionsListUtils.getHeaderMessage( + filteredPersonalDetails.length + filteredRecentReports.length !== 0, + Boolean(filteredUserToInvite), + searchTerm, + maxParticipantsReached, + ); + const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(props.personalDetails); + + const sections = useMemo(() => { + const sectionsList = []; let indexOffset = 0; - if (this.props.isGroupChat) { - sections.push({ + if (props.isGroupChat) { + sectionsList.push({ title: undefined, - data: this.state.selectedOptions, - shouldShow: !_.isEmpty(this.state.selectedOptions), + data: selectedOptions, + shouldShow: !_.isEmpty(selectedOptions), indexOffset, }); - indexOffset += this.state.selectedOptions.length; + indexOffset += selectedOptions.length; if (maxParticipantsReached) { - return sections; + return sectionsList; } } // Filtering out selected users from the search results - const filterText = _.reduce(this.state.selectedOptions, (str, {login}) => `${str} ${login}`, ''); - const recentReportsWithoutSelected = _.filter(this.state.recentReports, ({login}) => !filterText.includes(login)); - const personalDetailsWithoutSelected = _.filter(this.state.personalDetails, ({login}) => !filterText.includes(login)); - const hasUnselectedUserToInvite = this.state.userToInvite && !filterText.includes(this.state.userToInvite.login); + const filterText = _.reduce(selectedOptions, (str, {login}) => `${str} ${login}`, ''); + const recentReportsWithoutSelected = _.filter(filteredRecentReports, ({login}) => !filterText.includes(login)); + const personalDetailsWithoutSelected = _.filter(filteredPersonalDetails, ({login}) => !filterText.includes(login)); + const hasUnselectedUserToInvite = filteredUserToInvite && !filterText.includes(filteredUserToInvite.login); - sections.push({ - title: this.props.translate('common.recents'), + sectionsList.push({ + title: props.translate('common.recents'), data: recentReportsWithoutSelected, shouldShow: !_.isEmpty(recentReportsWithoutSelected), indexOffset, }); indexOffset += recentReportsWithoutSelected.length; - sections.push({ - title: this.props.translate('common.contacts'), + sectionsList.push({ + title: props.translate('common.contacts'), data: personalDetailsWithoutSelected, shouldShow: !_.isEmpty(personalDetailsWithoutSelected), indexOffset, @@ -125,67 +102,61 @@ class NewChatPage extends Component { indexOffset += personalDetailsWithoutSelected.length; if (hasUnselectedUserToInvite) { - sections.push({ + sectionsList.push({ title: undefined, - data: [this.state.userToInvite], + data: [filteredUserToInvite], shouldShow: true, indexOffset, }); } - return sections; - } + return sectionsList; + // eslint-disable-next-line react-hooks/exhaustive-deps -- to avoid destructuring props and adding all 'props' as a dependency + }, [props.isGroupChat, props.translate, selectedOptions, filteredRecentReports, filteredPersonalDetails, filteredUserToInvite, maxParticipantsReached]); - updateOptionsWithSearchTerm(searchTerm = '') { + const updateOptionsWithSearchTerm = (newSearchTerm = '') => { const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions( - this.props.reports, - this.props.personalDetails, - this.props.betas, - searchTerm, + props.reports, + props.personalDetails, + props.betas, + newSearchTerm, [], - this.props.isGroupChat ? this.excludedGroupEmails : [], + props.isGroupChat ? excludedGroupEmails : [], ); - this.setState({ - searchTerm, - userToInvite, - recentReports, - personalDetails, - }); - } + setSearchTerm(newSearchTerm); + setFilteredRecentReports(recentReports); + setFilteredPersonalDetails(personalDetails); + setFilteredUserToInvite(userToInvite); + }; /** * Removes a selected option from list if already selected. If not already selected add this option to the list. * @param {Object} option */ - toggleOption(option) { - this.setState((prevState) => { - const isOptionInList = _.some(prevState.selectedOptions, (selectedOption) => selectedOption.login === option.login); + const toggleOption = (option) => { + const isOptionInList = _.some(selectedOptions, (selectedOption) => selectedOption.login === option.login); - let newSelectedOptions; + let newSelectedOptions; - if (isOptionInList) { - newSelectedOptions = _.reject(prevState.selectedOptions, (selectedOption) => selectedOption.login === option.login); - } else { - newSelectedOptions = [...prevState.selectedOptions, option]; - } + if (isOptionInList) { + newSelectedOptions = _.reject(selectedOptions, (selectedOption) => selectedOption.login === option.login); + } else { + newSelectedOptions = [...selectedOptions, option]; + } - const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions( - this.props.reports, - this.props.personalDetails, - this.props.betas, - prevState.searchTerm, - [], - this.excludedGroupEmails, - ); + const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions( + props.reports, + props.personalDetails, + props.betas, + searchTerm, + [], + excludedGroupEmails, + ); - return { - selectedOptions: newSelectedOptions, - recentReports, - personalDetails, - userToInvite, - searchTerm: prevState.searchTerm, - }; - }); + setSelectedOptions(newSelectedOptions); + setFilteredRecentReports(recentReports); + setFilteredPersonalDetails(personalDetails); + setFilteredUserToInvite(userToInvite); } /** @@ -194,7 +165,7 @@ class NewChatPage extends Component { * * @param {Object} option */ - createChat(option) { + const createChat = (option) => { Report.navigateToAndOpenReport([option.login]); } @@ -202,68 +173,65 @@ class NewChatPage extends Component { * Creates a new group chat with all the selected options and the current user, * or navigates to the existing chat if one with those participants already exists. */ - createGroup() { - if (!this.props.isGroupChat) { + const createGroup = () => { + if (!props.isGroupChat) { return; } - const userLogins = _.pluck(this.state.selectedOptions, 'login'); + const userLogins = _.pluck(selectedOptions, 'login'); if (userLogins.length < 1) { return; } Report.navigateToAndOpenReport(userLogins); } - render() { - const maxParticipantsReached = this.state.selectedOptions.length === CONST.REPORT.MAXIMUM_PARTICIPANTS; - const sections = this.getSections(maxParticipantsReached); - const headerMessage = OptionsListUtils.getHeaderMessage( - this.state.personalDetails.length + this.state.recentReports.length !== 0, - Boolean(this.state.userToInvite), - this.state.searchTerm, - maxParticipantsReached, - ); - const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(this.props.personalDetails); - - return ( - - {({didScreenTransitionEnd, safeAreaPaddingBottomStyle}) => ( - <> - Navigation.dismissModal(true)} + useEffect(() => { + updateOptionsWithSearchTerm(searchTerm); + // all dependencies are not added below - + // 1. searchTerm - when searchTerm changes updateOptionsWithSearchTerm is called by OptionsSelector's onChangeText prop + // 2. updateOptionsWithSearchTerm - it will change its reference upon each rerender unnecessarily + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [props.reports, props.personalDetails]); + + return ( + + {({didScreenTransitionEnd, safeAreaPaddingBottomStyle}) => ( + <> + Navigation.dismissModal(true)} + /> + 0 ? safeAreaPaddingBottomStyle : {}]}> + (props.isGroupChat ? toggleOption(option) : createChat(option))} + onChangeText={updateOptionsWithSearchTerm} + headerMessage={headerMessage} + boldStyle + shouldFocusOnSelectRow={props.isGroupChat} + shouldShowConfirmButton={props.isGroupChat} + shouldShowOptions={didScreenTransitionEnd && isOptionsDataReady} + confirmButtonText={props.translate('newChatPage.createGroup')} + onConfirmSelection={createGroup} + textInputLabel={props.translate('optionsSelector.nameEmailOrPhoneNumber')} + safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle} /> - 0 ? safeAreaPaddingBottomStyle : {}]}> - (this.props.isGroupChat ? this.toggleOption(option) : this.createChat(option))} - onChangeText={this.updateOptionsWithSearchTerm} - headerMessage={headerMessage} - boldStyle - shouldFocusOnSelectRow={this.props.isGroupChat} - shouldShowConfirmButton={this.props.isGroupChat} - shouldShowOptions={didScreenTransitionEnd && isOptionsDataReady} - confirmButtonText={this.props.translate('newChatPage.createGroup')} - onConfirmSelection={this.createGroup} - textInputLabel={this.props.translate('optionsSelector.nameEmailOrPhoneNumber')} - safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle} - /> - - - )} - - ); - } -} + + + )} + + ); +}; NewChatPage.propTypes = propTypes; NewChatPage.defaultProps = defaultProps; +NewChatPage.displayName = 'NewChatPage'; export default compose( withLocalize, From a357a85e5f415cd9cf6b4af5982c77659fe121e9 Mon Sep 17 00:00:00 2001 From: Nikhil Vats Date: Mon, 5 Jun 2023 19:49:45 +0530 Subject: [PATCH 2/9] fix linting issues --- src/pages/NewChatPage.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index d241c46415f4..e43d0a81d586 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -144,20 +144,13 @@ const NewChatPage = (props) => { newSelectedOptions = [...selectedOptions, option]; } - const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions( - props.reports, - props.personalDetails, - props.betas, - searchTerm, - [], - excludedGroupEmails, - ); + const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions(props.reports, props.personalDetails, props.betas, searchTerm, [], excludedGroupEmails); setSelectedOptions(newSelectedOptions); setFilteredRecentReports(recentReports); setFilteredPersonalDetails(personalDetails); setFilteredUserToInvite(userToInvite); - } + }; /** * Creates a new 1:1 chat with the option and the current user, @@ -167,7 +160,7 @@ const NewChatPage = (props) => { */ const createChat = (option) => { Report.navigateToAndOpenReport([option.login]); - } + }; /** * Creates a new group chat with all the selected options and the current user, @@ -183,7 +176,7 @@ const NewChatPage = (props) => { return; } Report.navigateToAndOpenReport(userLogins); - } + }; useEffect(() => { updateOptionsWithSearchTerm(searchTerm); From 13d2e602f3c8383503b61bb51ea5fdc14a8e7845 Mon Sep 17 00:00:00 2001 From: Nikhil Vats Date: Tue, 6 Jun 2023 00:13:14 +0530 Subject: [PATCH 3/9] use function instead of const --- src/pages/NewChatPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index e43d0a81d586..6ee132c4abd6 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -44,7 +44,7 @@ const defaultProps = { reports: {}, }; -const NewChatPage = (props) => { +function NewChatPage(props) { const [searchTerm, setSearchTerm] = useState(''); const [filteredRecentReports, setFilteredRecentReports] = useState([]); const [filteredPersonalDetails, setFilteredPersonalDetails] = useState([]); From a75802f4c84f55cf13f9a215e8b2a8fe4cf1b24a Mon Sep 17 00:00:00 2001 From: Nikhil Vats Date: Wed, 7 Jun 2023 20:34:31 +0530 Subject: [PATCH 4/9] fix linting issues --- src/pages/NewChatPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index ce5b11c703ad..80e39422821b 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -216,7 +216,7 @@ function NewChatPage(props) { )} ); -}; +} NewChatPage.propTypes = propTypes; NewChatPage.defaultProps = defaultProps; From 81158575786f1375fe94f695f7fbda3dd53a8daf Mon Sep 17 00:00:00 2001 From: Nikhil Vats Date: Thu, 15 Jun 2023 15:53:03 +0530 Subject: [PATCH 5/9] Change const to function --- src/pages/NewChatPage.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 80e39422821b..0eb28f5a8c75 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -1,5 +1,5 @@ import _ from 'underscore'; -import React, {useState, useEffect, useMemo} from 'react'; +import React, {useState, useEffect} from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; @@ -60,7 +60,7 @@ function NewChatPage(props) { ); const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(props.personalDetails); - const sections = useMemo(() => { + function getSections() { const sectionsList = []; let indexOffset = 0; @@ -110,8 +110,7 @@ function NewChatPage(props) { } return sectionsList; - // eslint-disable-next-line react-hooks/exhaustive-deps -- to avoid destructuring props and adding all 'props' as a dependency - }, [props.isGroupChat, props.translate, selectedOptions, filteredRecentReports, filteredPersonalDetails, filteredUserToInvite, maxParticipantsReached]); + } const updateOptionsWithSearchTerm = (newSearchTerm = '') => { const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions( @@ -132,7 +131,7 @@ function NewChatPage(props) { * Removes a selected option from list if already selected. If not already selected add this option to the list. * @param {Object} option */ - const toggleOption = (option) => { + function toggleOption(option) { const isOptionInList = _.some(selectedOptions, (selectedOption) => selectedOption.login === option.login); let newSelectedOptions; @@ -149,7 +148,7 @@ function NewChatPage(props) { setFilteredRecentReports(recentReports); setFilteredPersonalDetails(personalDetails); setFilteredUserToInvite(userToInvite); - }; + } /** * Creates a new 1:1 chat with the option and the current user, @@ -157,9 +156,9 @@ function NewChatPage(props) { * * @param {Object} option */ - const createChat = (option) => { + function createChat(option) { Report.navigateToAndOpenReport([option.login]); - }; + } /** * Creates a new group chat with all the selected options and the current user, @@ -185,6 +184,8 @@ function NewChatPage(props) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.reports, props.personalDetails]); + const sections = getSections(); + return ( Date: Tue, 20 Jun 2023 19:55:14 +0530 Subject: [PATCH 6/9] Fix wrongly merged code --- src/pages/NewChatPage.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 159500a22367..ed8ddf69b18f 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -14,6 +14,7 @@ import withWindowDimensions, {windowDimensionsPropTypes} from '../components/wit import HeaderWithBackButton from '../components/HeaderWithBackButton'; import ScreenWrapper from '../components/ScreenWrapper'; import withLocalize, {withLocalizePropTypes} from '../components/withLocalize'; +import * as Browser from '../libs/Browser'; import compose from '../libs/compose'; import personalDetailsPropType from './personalDetailsPropType'; import reportPropTypes from './reportPropTypes'; @@ -203,7 +204,7 @@ function NewChatPage(props) { onChangeText={updateOptionsWithSearchTerm} headerMessage={headerMessage} boldStyle - shouldFocusOnSelectRow={props.isGroupChat} + shouldFocusOnSelectRow={props.isGroupChat && !Browser.isMobile()} shouldShowConfirmButton={props.isGroupChat} shouldShowOptions={didScreenTransitionEnd && isOptionsDataReady} confirmButtonText={props.translate('newChatPage.createGroup')} From 80a9a9b0c44e9ddf79611f36c1c4a4b6fba23905 Mon Sep 17 00:00:00 2001 From: Nikhil Vats Date: Tue, 20 Jun 2023 20:01:38 +0530 Subject: [PATCH 7/9] fix lint --- src/pages/NewChatPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index ed8ddf69b18f..7585c979b2b4 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -174,7 +174,7 @@ function NewChatPage(props) { return; } Report.navigateToAndOpenReport(logins); - } + }; useEffect(() => { updateOptionsWithSearchTerm(searchTerm); From 56b54915b82b37fef47834763d990e8915f3f1cf Mon Sep 17 00:00:00 2001 From: Nikhil Vats Date: Wed, 21 Jun 2023 23:23:13 +0530 Subject: [PATCH 8/9] Use useMemo hook --- src/pages/NewChatPage.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index 7585c979b2b4..e6f0472241dc 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -1,5 +1,5 @@ import _ from 'underscore'; -import React, {useState, useEffect} from 'react'; +import React, {useState, useEffect, useMemo} from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; @@ -61,7 +61,7 @@ function NewChatPage(props) { ); const isOptionsDataReady = ReportUtils.isReportDataReady() && OptionsListUtils.isPersonalDetailsReady(props.personalDetails); - function getSections() { + const sections = useMemo(() => { const sectionsList = []; let indexOffset = 0; @@ -111,7 +111,8 @@ function NewChatPage(props) { } return sectionsList; - } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [filteredPersonalDetails, filteredRecentReports, filteredUserToInvite, maxParticipantsReached, props.isGroupChat, selectedOptions]); const updateOptionsWithSearchTerm = (newSearchTerm = '') => { const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions( @@ -184,8 +185,6 @@ function NewChatPage(props) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.reports, props.personalDetails]); - const sections = getSections(); - return ( Date: Wed, 28 Jun 2023 19:52:44 +0530 Subject: [PATCH 9/9] Remove updateOptionsWithSearchTerm and use useEffect --- src/pages/NewChatPage.js | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/pages/NewChatPage.js b/src/pages/NewChatPage.js index e6f0472241dc..8927088c3f67 100755 --- a/src/pages/NewChatPage.js +++ b/src/pages/NewChatPage.js @@ -44,6 +44,8 @@ const defaultProps = { reports: {}, }; +const excludedGroupEmails = _.without(CONST.EXPENSIFY_EMAILS, CONST.EMAIL.CONCIERGE); + function NewChatPage(props) { const [searchTerm, setSearchTerm] = useState(''); const [filteredRecentReports, setFilteredRecentReports] = useState([]); @@ -51,7 +53,6 @@ function NewChatPage(props) { const [filteredUserToInvite, setFilteredUserToInvite] = useState(); const [selectedOptions, setSelectedOptions] = useState([]); - const excludedGroupEmails = _.without(CONST.EXPENSIFY_EMAILS, CONST.EMAIL.CONCIERGE); const maxParticipantsReached = selectedOptions.length === CONST.REPORT.MAXIMUM_PARTICIPANTS; const headerMessage = OptionsListUtils.getHeaderMessage( filteredPersonalDetails.length + filteredRecentReports.length !== 0, @@ -114,21 +115,6 @@ function NewChatPage(props) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [filteredPersonalDetails, filteredRecentReports, filteredUserToInvite, maxParticipantsReached, props.isGroupChat, selectedOptions]); - const updateOptionsWithSearchTerm = (newSearchTerm = '') => { - const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions( - props.reports, - props.personalDetails, - props.betas, - newSearchTerm, - [], - props.isGroupChat ? excludedGroupEmails : [], - ); - setSearchTerm(newSearchTerm); - setFilteredRecentReports(recentReports); - setFilteredPersonalDetails(personalDetails); - setFilteredUserToInvite(userToInvite); - }; - /** * Removes a selected option from list if already selected. If not already selected add this option to the list. * @param {Object} option @@ -178,12 +164,20 @@ function NewChatPage(props) { }; useEffect(() => { - updateOptionsWithSearchTerm(searchTerm); - // all dependencies are not added below - - // 1. searchTerm - when searchTerm changes updateOptionsWithSearchTerm is called by OptionsSelector's onChangeText prop - // 2. updateOptionsWithSearchTerm - it will change its reference upon each rerender unnecessarily + const {recentReports, personalDetails, userToInvite} = OptionsListUtils.getNewChatOptions( + props.reports, + props.personalDetails, + props.betas, + searchTerm, + [], + props.isGroupChat ? excludedGroupEmails : [], + ); + setFilteredRecentReports(recentReports); + setFilteredPersonalDetails(personalDetails); + setFilteredUserToInvite(userToInvite); + // props.betas and props.isGroupChat are not added as dependencies since they don't change during the component lifecycle // eslint-disable-next-line react-hooks/exhaustive-deps - }, [props.reports, props.personalDetails]); + }, [props.reports, props.personalDetails, searchTerm]); return ( (props.isGroupChat ? toggleOption(option) : createChat(option))} - onChangeText={updateOptionsWithSearchTerm} + onChangeText={setSearchTerm} headerMessage={headerMessage} boldStyle shouldFocusOnSelectRow={props.isGroupChat && !Browser.isMobile()}