diff --git a/src/pages/settings/Profile/PronounsPage.tsx b/src/pages/settings/Profile/PronounsPage.tsx
index 705a83e3ac46..d56291dbc139 100644
--- a/src/pages/settings/Profile/PronounsPage.tsx
+++ b/src/pages/settings/Profile/PronounsPage.tsx
@@ -1,4 +1,4 @@
-import React, {useEffect, useMemo, useRef, useState} from 'react';
+import React, {useCallback, useEffect, useMemo, useState} from 'react';
import CollapsibleHeaderOnKeyboard from '@components/CollapsibleHeaderOnKeyboard';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
@@ -31,7 +31,7 @@ function PronounsPage({currentUserPersonalDetails}: PronounsPageProps) {
const currentPronouns = currentUserPersonalDetails?.pronouns ?? '';
const currentPronounsKey = currentPronouns.substring(CONST.PRONOUNS.PREFIX.length);
const [searchValue, setSearchValue] = useState('');
- const isOptionSelected = useRef(false);
+ const [selectedPronouns, setSelectedPronouns] = useState(currentPronouns);
const currentUserAccountID = currentUserPersonalDetails?.accountID ?? CONST.DEFAULT_NUMBER_ID;
useEffect(() => {
@@ -41,6 +41,7 @@ function PronounsPage({currentUserPersonalDetails}: PronounsPageProps) {
const currentPronounsText = CONST.PRONOUNS_LIST.find((value) => value === currentPronounsKey);
setSearchValue(currentPronounsText ? translate(`pronouns.${currentPronounsText}`) : '');
+ setSelectedPronouns(currentPronouns);
// Only need to update search value when the first time the data is loaded
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -49,13 +50,12 @@ function PronounsPage({currentUserPersonalDetails}: PronounsPageProps) {
const filteredPronounsList = useMemo((): PronounEntry[] => {
const pronouns = CONST.PRONOUNS_LIST.map((value) => {
const fullPronounKey = `${CONST.PRONOUNS.PREFIX}${value}`;
- const isCurrentPronouns = fullPronounKey === currentPronouns;
return {
text: translate(`pronouns.${value}`),
value: fullPronounKey,
keyForList: value,
- isSelected: isCurrentPronouns,
+ isSelected: fullPronounKey === selectedPronouns,
};
}).sort((a, b) => localeCompare(a.text.toLowerCase(), b.text.toLowerCase()));
@@ -65,17 +65,26 @@ function PronounsPage({currentUserPersonalDetails}: PronounsPageProps) {
return [];
}
return pronouns.filter((pronoun) => pronoun.text.toLowerCase().indexOf(trimmedSearch.toLowerCase()) >= 0);
- }, [searchValue, currentPronouns, translate, localeCompare]);
+ }, [searchValue, selectedPronouns, translate, localeCompare]);
- const updatePronouns = (selectedPronouns: PronounEntry) => {
- if (isOptionSelected.current) {
- return;
- }
- isOptionSelected.current = true;
- updatePronounsPersonalDetails(selectedPronouns.keyForList === currentPronounsKey ? '' : (selectedPronouns?.value ?? ''), currentUserAccountID);
- Navigation.goBack();
+ const selectPronoun = (selectedPronoun: PronounEntry) => {
+ setSelectedPronouns(selectedPronoun.value === selectedPronouns ? '' : (selectedPronoun?.value ?? ''));
};
+ const savePronouns = useCallback(() => {
+ updatePronounsPersonalDetails(selectedPronouns, currentUserAccountID);
+ Navigation.goBack();
+ }, [selectedPronouns, currentUserAccountID]);
+
+ const confirmButtonOptions = useMemo(
+ () => ({
+ showButton: true,
+ text: translate('common.save'),
+ onConfirm: savePronouns,
+ }),
+ [savePronouns, translate],
+ );
+
const textInputOptions = useMemo(
() => ({
label: translate('pronounsPage.pronouns'),
@@ -107,9 +116,10 @@ function PronounsPage({currentUserPersonalDetails}: PronounsPageProps) {
>
diff --git a/src/pages/workspace/rules/RulesReimbursableDefaultPage.tsx b/src/pages/workspace/rules/RulesReimbursableDefaultPage.tsx
index 065a4dcc0a56..0cd55451553a 100644
--- a/src/pages/workspace/rules/RulesReimbursableDefaultPage.tsx
+++ b/src/pages/workspace/rules/RulesReimbursableDefaultPage.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, {useCallback, useMemo, useState} from 'react';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import SelectionList from '@components/SelectionList';
@@ -28,14 +28,36 @@ function RulesReimbursableDefaultPage({
const reimbursableMode = getCashExpenseReimbursableMode(policy);
+ // The draft holds the user's in-page selection. Until they pick a row it stays undefined and we fall back to the
+ // persisted reimbursableMode, which also covers the page rendering before the policy is in Onyx.
+ const [draftMode, setDraftMode] = useState();
+ const selectedMode = draftMode ?? reimbursableMode;
+
const reimbursableModes = Object.values(CONST.POLICY.CASH_EXPENSE_REIMBURSEMENT_CHOICES).map((mode) => ({
text: translate(`workspace.rules.individualExpenseRules.${mode}`),
alternateText: translate(`workspace.rules.individualExpenseRules.${mode}Description`),
value: mode,
- isSelected: reimbursableMode === mode,
+ isSelected: selectedMode === mode,
keyForList: mode,
}));
+ const saveAndGoBack = useCallback(() => {
+ if (!selectedMode) {
+ return;
+ }
+ setPolicyReimbursableMode(policyID, selectedMode, policy?.defaultReimbursable, policy?.disabledFields?.reimbursable);
+ Navigation.goBack();
+ }, [policyID, selectedMode, policy?.defaultReimbursable, policy?.disabledFields?.reimbursable]);
+
+ const confirmButtonOptions = useMemo(
+ () => ({
+ showButton: true,
+ text: translate('common.save'),
+ onConfirm: saveAndGoBack,
+ }),
+ [saveAndGoBack, translate],
+ );
+
return (
{
- setPolicyReimbursableMode(policyID, item.value, policy?.defaultReimbursable, policy?.disabledFields?.reimbursable);
- Navigation.setNavigationActionToMicrotaskQueue(Navigation.goBack);
+ setDraftMode(item.value);
}}
+ confirmButtonOptions={confirmButtonOptions}
shouldSingleExecuteRowSelect
style={{containerStyle: styles.pt3}}
initiallyFocusedItemKey={reimbursableMode}