From ba2670c136229a2f74c7238a3999383b3cd6ccbd Mon Sep 17 00:00:00 2001 From: war-in Date: Thu, 24 Apr 2025 13:08:30 +0200 Subject: [PATCH 1/5] add initialValue for every useRef --- src/components/AddPlaidBankAccount.tsx | 2 +- src/components/EmojiPicker/EmojiPicker.tsx | 4 ++-- src/components/Image/index.tsx | 2 +- src/components/LHNOptionsList/OptionRowLHNData.tsx | 2 +- src/components/MagicCodeInput.tsx | 2 +- src/components/Modal/BottomDockedModal/index.tsx | 2 +- src/components/MoneyReportHeader.tsx | 2 +- src/components/PDFView/PDFPasswordForm.tsx | 2 +- src/components/QRShare/index.tsx | 2 +- .../Search/SearchRouter/SearchRouterContext.tsx | 2 +- .../SettlementButton/AnimatedSettlementButton.tsx | 2 +- .../EducationalTooltip/BaseEducationalTooltip.tsx | 2 +- .../ValidateCodeForm/BaseValidateCodeForm.tsx | 2 +- src/components/VideoPlayer/BaseVideoPlayer.tsx | 2 +- .../PlaybackContext/usePlaybackContextVideoRefs.ts | 2 +- src/hooks/useDeepCompareRef.ts | 2 +- src/hooks/useSingleExecution/index.native.ts | 2 +- .../ContextMenu/PopoverReportActionContextMenu.tsx | 10 +++++----- .../ComposerWithSuggestions/index.e2e.tsx | 4 ++-- .../report/ReportActionCompose/ReportActionCompose.tsx | 2 +- .../iou/request/step/DiscardChangesConfirmation.tsx | 2 +- .../iou/request/step/IOURequestStepTaxAmountPage.tsx | 4 ++-- .../signin/ValidateCodeForm/BaseValidateCodeForm.tsx | 6 +++--- 23 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/components/AddPlaidBankAccount.tsx b/src/components/AddPlaidBankAccount.tsx index 11b0010ed253..3ee199e2739c 100644 --- a/src/components/AddPlaidBankAccount.tsx +++ b/src/components/AddPlaidBankAccount.tsx @@ -91,7 +91,7 @@ function AddPlaidBankAccount({ const defaultSelectedPlaidAccountID = defaultSelectedPlaidAccount?.plaidAccountID ?? '-1'; const defaultSelectedPlaidAccountMask = plaidBankAccounts.find((account) => account.plaidAccountID === selectedPlaidAccountID)?.mask ?? ''; const subscribedKeyboardShortcuts = useRef void>>([]); - const previousNetworkState = useRef(); + const previousNetworkState = useRef(undefined); const [selectedPlaidAccountMask, setSelectedPlaidAccountMask] = useState(defaultSelectedPlaidAccountMask); const {translate} = useLocalize(); diff --git a/src/components/EmojiPicker/EmojiPicker.tsx b/src/components/EmojiPicker/EmojiPicker.tsx index 51ae120d80bf..e16a31248a59 100644 --- a/src/components/EmojiPicker/EmojiPicker.tsx +++ b/src/components/EmojiPicker/EmojiPicker.tsx @@ -44,8 +44,8 @@ function EmojiPicker({viewportOffsetTop}: EmojiPickerProps, ref: ForwardedRef(() => {}); const onEmojiSelected = useRef(() => {}); - const activeEmoji = useRef(); - const emojiSearchInput = useRef(); + const activeEmoji = useRef(undefined); + const emojiSearchInput = useRef(null); const {windowHeight} = useWindowDimensions(); const {shouldUseNarrowLayout} = useResponsiveLayout(); diff --git a/src/components/Image/index.tsx b/src/components/Image/index.tsx index 2c01ebe9b617..097efcf2ed37 100644 --- a/src/components/Image/index.tsx +++ b/src/components/Image/index.tsx @@ -52,7 +52,7 @@ function Image({source: propsSource, isAuthTokenRequired = false, onLoad, object /** * trying to figure out if the current session is expired or fresh from a necessary reauthentication */ - const previousSessionAge = useRef(); + const previousSessionAge = useRef(undefined); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const validSessionAge: number | undefined = useMemo(() => { // Authentication is required only for certain types of images (attachments and receipts), diff --git a/src/components/LHNOptionsList/OptionRowLHNData.tsx b/src/components/LHNOptionsList/OptionRowLHNData.tsx index 27bf69a58159..228d14a1e2b5 100644 --- a/src/components/LHNOptionsList/OptionRowLHNData.tsx +++ b/src/components/LHNOptionsList/OptionRowLHNData.tsx @@ -37,7 +37,7 @@ function OptionRowLHNData({ const currentReportIDValue = useCurrentReportID(); const isReportFocused = isFocused && currentReportIDValue?.currentReportID === reportID; - const optionItemRef = useRef(); + const optionItemRef = useRef(undefined); const shouldDisplayViolations = shouldDisplayViolationsRBRInLHN(fullReport, transactionViolations); const isReportSettled = isSettled(fullReport); diff --git a/src/components/MagicCodeInput.tsx b/src/components/MagicCodeInput.tsx index 164148402013..e989e515c62b 100644 --- a/src/components/MagicCodeInput.tsx +++ b/src/components/MagicCodeInput.tsx @@ -114,7 +114,7 @@ function MagicCodeInput( ) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); - const inputRef = useRef(); + const inputRef = useRef(null); const [input, setInput] = useState(TEXT_INPUT_EMPTY_STATE); const [focusedIndex, setFocusedIndex] = useState(0); const editIndex = useRef(0); diff --git a/src/components/Modal/BottomDockedModal/index.tsx b/src/components/Modal/BottomDockedModal/index.tsx index bce18d706686..6a7257c8aa7c 100644 --- a/src/components/Modal/BottomDockedModal/index.tsx +++ b/src/components/Modal/BottomDockedModal/index.tsx @@ -42,7 +42,7 @@ function BottomDockedModal({ const [deviceWidth, setDeviceWidth] = useState(() => Dimensions.get('window').width); const [deviceHeight, setDeviceHeight] = useState(() => Dimensions.get('window').height); const backHandlerListener = useRef(null); - const handleRef = useRef(); + const handleRef = useRef(undefined); const styles = useThemeStyles(); diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index fdff6c8e7697..7d8d54f92ffb 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -164,7 +164,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea const canAllowSettlement = hasUpdatedTotal(moneyRequestReport, policy); const policyType = policy?.type; const connectedIntegration = getConnectedIntegration(policy); - const navigateBackToAfterDelete = useRef(); + const navigateBackToAfterDelete = useRef(undefined); const hasScanningReceipt = getTransactionsWithReceipts(moneyRequestReport?.reportID).some((t) => isReceiptBeingScanned(t)); const hasOnlyPendingTransactions = useMemo(() => { return !!transactions && transactions.length > 0 && transactions.every((t) => isExpensifyCardTransaction(t) && isPending(t)); diff --git a/src/components/PDFView/PDFPasswordForm.tsx b/src/components/PDFView/PDFPasswordForm.tsx index 8cd886f31b16..ef2a5546613a 100644 --- a/src/components/PDFView/PDFPasswordForm.tsx +++ b/src/components/PDFView/PDFPasswordForm.tsx @@ -43,7 +43,7 @@ function PDFPasswordForm({isFocused, isPasswordInvalid = false, shouldShowLoadin const [shouldShowForm, setShouldShowForm] = useState(false); const textInputRef = useRef(null); - const focusTimeoutRef = useRef(); + const focusTimeoutRef = useRef(undefined); const errorText = useMemo(() => { if (isPasswordInvalid) { diff --git a/src/components/QRShare/index.tsx b/src/components/QRShare/index.tsx index 9e8d11ea9664..7dbdf2d93265 100644 --- a/src/components/QRShare/index.tsx +++ b/src/components/QRShare/index.tsx @@ -22,7 +22,7 @@ function QRShare({url, title, subtitle, logo, svgLogo, svgLogoFillColor, logoBac const qrCodeContainerWidth = shouldUseNarrowLayout ? windowWidth : variables.sideBarWidth; const [qrCodeSize, setQrCodeSize] = useState(qrCodeContainerWidth - styles.ph5.paddingHorizontal * 2 - variables.qrShareHorizontalPadding * 2); - const svgRef = useRef(); + const svgRef = useRef(undefined); useImperativeHandle( ref, diff --git a/src/components/Search/SearchRouter/SearchRouterContext.tsx b/src/components/Search/SearchRouter/SearchRouterContext.tsx index c4bc96e9855e..fa60646ec3ee 100644 --- a/src/components/Search/SearchRouter/SearchRouterContext.tsx +++ b/src/components/Search/SearchRouter/SearchRouterContext.tsx @@ -30,7 +30,7 @@ const Context = React.createContext(defaultSearchContext); function SearchRouterContextProvider({children}: ChildrenProps) { const [isSearchRouterDisplayed, setIsSearchRouterDisplayed] = useState(false); const searchRouterDisplayedRef = useRef(false); - const searchPageInputRef = useRef(); + const searchPageInputRef = useRef(undefined); const routerContext = useMemo(() => { const openSearchRouter = () => { diff --git a/src/components/SettlementButton/AnimatedSettlementButton.tsx b/src/components/SettlementButton/AnimatedSettlementButton.tsx index 388297075082..7a0771b39d97 100644 --- a/src/components/SettlementButton/AnimatedSettlementButton.tsx +++ b/src/components/SettlementButton/AnimatedSettlementButton.tsx @@ -38,7 +38,7 @@ function AnimatedSettlementButton({ const height = useSharedValue(variables.componentSizeNormal); const [canShow, setCanShow] = React.useState(true); const [minWidth, setMinWidth] = React.useState(0); - const viewRef = useRef(); + const viewRef = useRef(null); const containerStyles = useAnimatedStyle(() => ({ height: height.get(), diff --git a/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx b/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx index 0406288aec02..664ca9ee45f4 100644 --- a/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx +++ b/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx @@ -20,7 +20,7 @@ type ScrollingEventData = { * This tooltip would show immediately without user's interaction and hide after 5 seconds. */ function BaseEducationalTooltip({children, shouldRender = false, shouldHideOnNavigate = true, shouldHideOnScroll = false, ...props}: EducationalTooltipProps) { - const genericTooltipStateRef = useRef(); + const genericTooltipStateRef = useRef(undefined); const tooltipElementRef = useRef>(); const [shouldMeasure, setShouldMeasure] = useState(false); diff --git a/src/components/ValidateCodeActionModal/ValidateCodeForm/BaseValidateCodeForm.tsx b/src/components/ValidateCodeActionModal/ValidateCodeForm/BaseValidateCodeForm.tsx index cc75dd9e6440..27b746e3fa92 100644 --- a/src/components/ValidateCodeActionModal/ValidateCodeForm/BaseValidateCodeForm.tsx +++ b/src/components/ValidateCodeActionModal/ValidateCodeForm/BaseValidateCodeForm.tsx @@ -122,7 +122,7 @@ function BaseValidateCodeForm({ const [canShowError, setCanShowError] = useState(false); const latestActionVerifiedError = getLatestErrorField(validateCodeAction, 'actionVerified'); - const timerRef = useRef(); + const timerRef = useRef(undefined); useImperativeHandle(innerRef, () => ({ focus() { diff --git a/src/components/VideoPlayer/BaseVideoPlayer.tsx b/src/components/VideoPlayer/BaseVideoPlayer.tsx index 251c74d4cbcc..b11cb7c991ec 100644 --- a/src/components/VideoPlayer/BaseVideoPlayer.tsx +++ b/src/components/VideoPlayer/BaseVideoPlayer.tsx @@ -336,7 +336,7 @@ function BaseVideoPlayer({ currentVideoPlayerRef.current = videoPlayerRef.current; }, [url, currentVideoPlayerRef, isUploading, pauseVideo]); - const isCurrentlyURLSetRef = useRef(); + const isCurrentlyURLSetRef = useRef(undefined); isCurrentlyURLSetRef.current = isCurrentlyURLSet; useEffect( diff --git a/src/components/VideoPlayerContexts/PlaybackContext/usePlaybackContextVideoRefs.ts b/src/components/VideoPlayerContexts/PlaybackContext/usePlaybackContextVideoRefs.ts index b072997579ab..f44703017f87 100644 --- a/src/components/VideoPlayerContexts/PlaybackContext/usePlaybackContextVideoRefs.ts +++ b/src/components/VideoPlayerContexts/PlaybackContext/usePlaybackContextVideoRefs.ts @@ -6,7 +6,7 @@ import type {PlaybackContextVideoRefs, PlayVideoPromiseRef, StopVideo, UnloadVid function usePlaybackContextVideoRefs(resetCallback: () => void) { const currentVideoPlayerRef: PlaybackContextVideoRefs['ref'] = useRef(null); const videoResumeTryNumberRef: PlaybackContextVideoRefs['resumeTryNumberRef'] = useRef(0); - const playVideoPromiseRef: PlayVideoPromiseRef = useRef(); + const playVideoPromiseRef: PlayVideoPromiseRef = useRef(undefined); const isPlayPendingRef = useRef(false); const pauseVideo: PlaybackContextVideoRefs['pause'] = useCallback(() => { diff --git a/src/hooks/useDeepCompareRef.ts b/src/hooks/useDeepCompareRef.ts index 9a226da44767..c06978ce03a6 100644 --- a/src/hooks/useDeepCompareRef.ts +++ b/src/hooks/useDeepCompareRef.ts @@ -16,7 +16,7 @@ import {useRef} from 'react'; * }, [deepComparedArray]); */ export default function useDeepCompareRef(value: T): T | undefined { - const ref = useRef(); + const ref = useRef(undefined); // eslint-disable-next-line react-compiler/react-compiler if (!isEqual(value, ref.current)) { // eslint-disable-next-line react-compiler/react-compiler diff --git a/src/hooks/useSingleExecution/index.native.ts b/src/hooks/useSingleExecution/index.native.ts index 736a79ab1810..3d69861d792f 100644 --- a/src/hooks/useSingleExecution/index.native.ts +++ b/src/hooks/useSingleExecution/index.native.ts @@ -8,7 +8,7 @@ type Action = (...params: T) => void | Promise; */ export default function useSingleExecution() { const [isExecuting, setIsExecuting] = useState(false); - const isExecutingRef = useRef(); + const isExecutingRef = useRef(undefined); // eslint-disable-next-line react-compiler/react-compiler isExecutingRef.current = isExecuting; diff --git a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx index 46d1912558b8..302105018664 100644 --- a/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/PopoverReportActionContextMenu.tsx @@ -34,13 +34,13 @@ function extractPointerEvent(event: GestureResponderEvent | MouseEvent): MouseEv function PopoverReportActionContextMenu(_props: unknown, ref: ForwardedRef) { const {translate} = useLocalize(); - const reportIDRef = useRef(); - const typeRef = useRef(); + const reportIDRef = useRef(undefined); + const typeRef = useRef(undefined); const reportActionRef = useRef> | null>(null); - const reportActionIDRef = useRef(); - const originalReportIDRef = useRef(); + const reportActionIDRef = useRef(undefined); + const originalReportIDRef = useRef(undefined); const selectionRef = useRef(''); - const reportActionDraftMessageRef = useRef(); + const reportActionDraftMessageRef = useRef(undefined); const cursorRelativePosition = useRef({ horizontal: 0, diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx index 336b5ab22424..ea6cf7c3409e 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx @@ -26,7 +26,7 @@ function ComposerWithSuggestionsE2e(props: ComposerWithSuggestionsProps, ref: Fo // for this component. This file is only used for e2e tests, so it's okay to // disable compiler for this file. - const textInputRef = useRef(); + const textInputRef = useRef(null); const hasFocusBeenRequested = useRef(false); const onLayout = useCallback((event: LayoutChangeEvent) => { const testConfig = E2EClient.getCurrentActiveTestConfig(); @@ -78,7 +78,7 @@ function ComposerWithSuggestionsE2e(props: ComposerWithSuggestionsProps, ref: Fo }} onLayout={onLayout} > - {/* Important: + {/* Important: this has to be a child, as this container might not re-render while the actual ComposerWithSuggestions will. */} diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index a102a4fa60f4..336e2a7c5b2c 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -168,7 +168,7 @@ function ReportActionCompose({ const [exceededMaxLength, setExceededMaxLength] = useState(null); const suggestionsRef = useRef(null); - const composerRef = useRef(); + const composerRef = useRef(undefined); const reportParticipantIDs = useMemo( () => Object.keys(report?.participants ?? {}) diff --git a/src/pages/iou/request/step/DiscardChangesConfirmation.tsx b/src/pages/iou/request/step/DiscardChangesConfirmation.tsx index 29cb40cf2dff..d47e2843b233 100644 --- a/src/pages/iou/request/step/DiscardChangesConfirmation.tsx +++ b/src/pages/iou/request/step/DiscardChangesConfirmation.tsx @@ -12,7 +12,7 @@ type DiscardChangesConfirmationProps = { function DiscardChangesConfirmation({getHasUnsavedChanges}: DiscardChangesConfirmationProps) { const {translate} = useLocalize(); const [isVisible, setIsVisible] = useState(false); - const blockedNavigationAction = useRef(); + const blockedNavigationAction = useRef(undefined); useBeforeRemove( useCallback( diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx index b3ed65be34a6..b1219779929b 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx @@ -65,11 +65,11 @@ function IOURequestStepTaxAmountPage({ splitDraftTransaction, }: IOURequestStepTaxAmountPageProps) { const {translate} = useLocalize(); - const textInput = useRef(); + const textInput = useRef(null); const isEditing = action === CONST.IOU.ACTION.EDIT; const isEditingSplitBill = isEditing && iouType === CONST.IOU.TYPE.SPLIT; - const focusTimeoutRef = useRef(); + const focusTimeoutRef = useRef(undefined); const currentTransaction = isEditingSplitBill && !isEmptyObject(splitDraftTransaction) ? splitDraftTransaction : transaction; const transactionDetails = ReportUtils.getTransactionDetails(currentTransaction); diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx index ebf8ecaccffb..ec2f3bb73572 100755 --- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx +++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx @@ -65,9 +65,9 @@ function BaseValidateCodeForm({autoComplete, isUsingRecoveryCode, setIsUsingReco const prevRequiresTwoFactorAuth = usePrevious(account?.requiresTwoFactorAuth); const prevValidateCode = usePrevious(credentials?.validateCode); - const inputValidateCodeRef = useRef(); - const input2FARef = useRef(); - const timerRef = useRef(); + const inputValidateCodeRef = useRef(undefined); + const input2FARef = useRef(undefined); + const timerRef = useRef(undefined); const hasError = !!account && !isEmptyObject(account?.errors) && !needToClearError; const isLoadingResendValidationForm = account?.loadingForm === CONST.FORMS.RESEND_VALIDATE_CODE_FORM; From 8a9af90914dd34fec296f9d6d3ac3ad7c8262f26 Mon Sep 17 00:00:00 2001 From: war-in Date: Thu, 24 Apr 2025 14:16:10 +0200 Subject: [PATCH 2/5] fix other lint issues --- src/components/AddPlaidBankAccount.tsx | 50 ++++------- src/libs/actions/IOU.ts | 2 +- .../step/IOURequestStepTaxAmountPage.tsx | 90 +++++++------------ 3 files changed, 50 insertions(+), 92 deletions(-) diff --git a/src/components/AddPlaidBankAccount.tsx b/src/components/AddPlaidBankAccount.tsx index 3ee199e2739c..a39c7e1e4097 100644 --- a/src/components/AddPlaidBankAccount.tsx +++ b/src/components/AddPlaidBankAccount.tsx @@ -1,15 +1,15 @@ import React, {useCallback, useEffect, useRef, useState} from 'react'; import {ActivityIndicator, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import {handlePlaidError, openPlaidBankAccountSelector, openPlaidBankLogin, setPlaidEvent} from '@libs/actions/BankAccounts'; import KeyboardShortcut from '@libs/KeyboardShortcut'; import Log from '@libs/Log'; -import * as App from '@userActions/App'; -import * as BankAccounts from '@userActions/BankAccounts'; +import {handleRestrictedEvent} from '@userActions/App'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PlaidData} from '@src/types/onyx'; @@ -22,15 +22,7 @@ import PlaidLink from './PlaidLink'; import RadioButtons from './RadioButtons'; import Text from './Text'; -type AddPlaidBankAccountOnyxProps = { - /** If the user has been throttled from Plaid */ - isPlaidDisabled: OnyxEntry; - - /** Plaid SDK token to use to initialize the widget */ - plaidLinkToken: OnyxEntry; -}; - -type AddPlaidBankAccountProps = AddPlaidBankAccountOnyxProps & { +type AddPlaidBankAccountProps = { /** Contains plaid data */ plaidData: OnyxEntry; @@ -71,7 +63,6 @@ type AddPlaidBankAccountProps = AddPlaidBankAccountOnyxProps & { function AddPlaidBankAccount({ plaidData, selectedPlaidAccountID = '', - plaidLinkToken, onExitPlaid = () => {}, onSelect = () => {}, text = '', @@ -79,16 +70,19 @@ function AddPlaidBankAccount({ plaidLinkOAuthToken = '', bankAccountID = 0, allowDebit = false, - isPlaidDisabled, errorText = '', onInputChange = () => {}, isDisplayedInWalletFlow = false, }: AddPlaidBankAccountProps) { const theme = useTheme(); const styles = useThemeStyles(); + + const [plaidLinkToken] = useOnyx(ONYXKEYS.PLAID_LINK_TOKEN, {initWithStoredValues: false}); + const [isPlaidDisabled] = useOnyx(ONYXKEYS.IS_PLAID_DISABLED); + const plaidBankAccounts = plaidData?.bankAccounts ?? []; const defaultSelectedPlaidAccount = plaidBankAccounts.find((account) => account.plaidAccountID === selectedPlaidAccountID); - const defaultSelectedPlaidAccountID = defaultSelectedPlaidAccount?.plaidAccountID ?? '-1'; + const defaultSelectedPlaidAccountID = defaultSelectedPlaidAccount?.plaidAccountID; const defaultSelectedPlaidAccountMask = plaidBankAccounts.find((account) => account.plaidAccountID === selectedPlaidAccountID)?.mask ?? ''; const subscribedKeyboardShortcuts = useRef void>>([]); const previousNetworkState = useRef(undefined); @@ -149,7 +143,7 @@ function AddPlaidBankAccount({ if (isAuthenticatedWithPlaid()) { return unsubscribeToNavigationShortcuts; } - BankAccounts.openPlaidBankLogin(allowDebit, bankAccountID); + openPlaidBankLogin(allowDebit, bankAccountID); return unsubscribeToNavigationShortcuts; // disabling this rule, as we want this to run only on the first render @@ -160,7 +154,7 @@ function AddPlaidBankAccount({ // If we are coming back from offline and we haven't authenticated with Plaid yet, we need to re-run our call to kick off Plaid // previousNetworkState.current also makes sure that this doesn't run on the first render. if (previousNetworkState.current && !isOffline && !isAuthenticatedWithPlaid()) { - BankAccounts.openPlaidBankLogin(allowDebit, bankAccountID); + openPlaidBankLogin(allowDebit, bankAccountID); } previousNetworkState.current = isOffline; }, [allowDebit, bankAccountID, isAuthenticatedWithPlaid, isOffline]); @@ -187,7 +181,7 @@ function AddPlaidBankAccount({ onInputChange(plaidAccountID); }; - const handlePlaidError = useCallback((error: ErrorEvent | null) => { + const handlePlaidLinkError = useCallback((error: ErrorEvent | null) => { Log.hmmm('[PlaidLink] Error: ', error?.message); }, []); @@ -206,22 +200,22 @@ function AddPlaidBankAccount({ token={token} onSuccess={({publicToken, metadata}) => { Log.info('[PlaidLink] Success!'); - BankAccounts.openPlaidBankAccountSelector(publicToken, metadata?.institution?.name ?? '', allowDebit, bankAccountID); + openPlaidBankAccountSelector(publicToken, metadata?.institution?.name ?? '', allowDebit, bankAccountID); }} - onError={handlePlaidError} + onError={handlePlaidLinkError} onEvent={(event, metadata) => { - BankAccounts.setPlaidEvent(event); + setPlaidEvent(event); // Handle Plaid login errors (will potentially reset plaid token and item depending on the error) if (event === 'ERROR') { Log.hmmm('[PlaidLink] Error: ', {...metadata}); if (bankAccountID && metadata && 'error_code' in metadata) { - BankAccounts.handlePlaidError(bankAccountID, metadata.error_code ?? '', metadata.error_message ?? '', metadata.request_id); + handlePlaidError(bankAccountID, metadata.error_code ?? '', metadata.error_message ?? '', metadata.request_id); } } // Limit the number of times a user can submit Plaid credentials if (event === 'SUBMIT_CREDENTIALS') { - App.handleRestrictedEvent(event); + handleRestrictedEvent(event); } }} // User prematurely exited the Plaid flow @@ -287,12 +281,4 @@ function AddPlaidBankAccount({ AddPlaidBankAccount.displayName = 'AddPlaidBankAccount'; -export default withOnyx({ - plaidLinkToken: { - key: ONYXKEYS.PLAID_LINK_TOKEN, - initWithStoredValues: false, - }, - isPlaidDisabled: { - key: ONYXKEYS.IS_PLAID_DISABLED, - }, -})(AddPlaidBankAccount); +export default AddPlaidBankAccount; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 86d302440567..6ad8bc4ac51c 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -4372,7 +4372,7 @@ function updateMoneyRequestTag( /** Updates the created tax amount of an expense */ function updateMoneyRequestTaxAmount( transactionID: string, - optimisticReportActionID: string, + optimisticReportActionID: string | undefined, taxAmount: number, policy: OnyxEntry, policyTagList: OnyxEntry, diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx index b1219779929b..a2a7d8a4e491 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx @@ -1,56 +1,44 @@ import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useRef} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; import useLocalize from '@hooks/useLocalize'; -import * as CurrencyUtils from '@libs/CurrencyUtils'; +import {setDraftSplitTransaction, setMoneyRequestCurrency, setMoneyRequestParticipantsFromReport, setMoneyRequestTaxAmount, updateMoneyRequestTaxAmount} from '@libs/actions/IOU'; +import {convertToBackendAmount, isValidCurrencyCode} from '@libs/CurrencyUtils'; import Navigation from '@libs/Navigation/Navigation'; -import * as ReportUtils from '@libs/ReportUtils'; -import * as TransactionUtils from '@libs/TransactionUtils'; +import {getTransactionDetails} from '@libs/ReportUtils'; +import {calculateTaxAmount, getAmount, getDefaultTaxCode, getTaxValue, getTaxAmount as getTransactionTaxAmount} from '@libs/TransactionUtils'; import type {CurrentMoney} from '@pages/iou/MoneyRequestAmountForm'; import MoneyRequestAmountForm from '@pages/iou/MoneyRequestAmountForm'; -import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import type {Policy, PolicyCategories, PolicyTagLists, Transaction} from '@src/types/onyx'; +import type {Policy, Transaction} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import StepScreenWrapper from './StepScreenWrapper'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; -type IOURequestStepTaxAmountPageOnyxProps = { - policy: OnyxEntry; - policyCategories: OnyxEntry; - - /** Collection of tag list on a policy */ - policyTags: OnyxEntry; - - /** The draft transaction that holds data to be persisted on the current transaction */ - splitDraftTransaction: OnyxEntry; +type IOURequestStepTaxAmountPageProps = WithWritableReportOrNotFoundProps & { + transaction: OnyxEntry; }; -type IOURequestStepTaxAmountPageProps = IOURequestStepTaxAmountPageOnyxProps & - WithWritableReportOrNotFoundProps & { - transaction: OnyxEntry; - }; - function getTaxAmount(transaction: OnyxEntry, policy: OnyxEntry, currency: string | undefined, isEditing: boolean): number | undefined { if (!transaction?.amount && !transaction?.modifiedAmount) { return; } - const transactionTaxAmount = TransactionUtils.getAmount(transaction); + const transactionTaxAmount = getAmount(transaction); const transactionTaxCode = transaction?.taxCode ?? ''; - const defaultTaxCode = TransactionUtils.getDefaultTaxCode(policy, transaction, currency) ?? ''; - const getTaxValue = (taxCode: string) => TransactionUtils.getTaxValue(policy, transaction, taxCode); - const defaultTaxValue = getTaxValue(defaultTaxCode); - const moneyRequestTaxPercentage = (transactionTaxCode ? getTaxValue(transactionTaxCode) : defaultTaxValue) ?? ''; - const editingTaxPercentage = (transactionTaxCode ? getTaxValue(transactionTaxCode) : moneyRequestTaxPercentage) ?? ''; + const defaultTaxCode = getDefaultTaxCode(policy, transaction, currency) ?? ''; + const getTaxValueByTaxCode = (taxCode: string) => getTaxValue(policy, transaction, taxCode); + const defaultTaxValue = getTaxValueByTaxCode(defaultTaxCode); + const moneyRequestTaxPercentage = (transactionTaxCode ? getTaxValueByTaxCode(transactionTaxCode) : defaultTaxValue) ?? ''; + const editingTaxPercentage = (transactionTaxCode ? getTaxValueByTaxCode(transactionTaxCode) : moneyRequestTaxPercentage) ?? ''; const taxPercentage = isEditing ? editingTaxPercentage : moneyRequestTaxPercentage; - return CurrencyUtils.convertToBackendAmount(TransactionUtils.calculateTaxAmount(taxPercentage, transactionTaxAmount, currency ?? CONST.CURRENCY.USD)); + return convertToBackendAmount(calculateTaxAmount(taxPercentage, transactionTaxAmount, currency ?? CONST.CURRENCY.USD)); } function IOURequestStepTaxAmountPage({ @@ -59,12 +47,14 @@ function IOURequestStepTaxAmountPage({ }, transaction, report, - policy, - policyTags, - policyCategories, - splitDraftTransaction, }: IOURequestStepTaxAmountPageProps) { const {translate} = useLocalize(); + + const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`); + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`); + const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report?.policyID}`); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`); + const textInput = useRef(null); const isEditing = action === CONST.IOU.ACTION.EDIT; const isEditingSplitBill = isEditing && iouType === CONST.IOU.TYPE.SPLIT; @@ -72,8 +62,8 @@ function IOURequestStepTaxAmountPage({ const focusTimeoutRef = useRef(undefined); const currentTransaction = isEditingSplitBill && !isEmptyObject(splitDraftTransaction) ? splitDraftTransaction : transaction; - const transactionDetails = ReportUtils.getTransactionDetails(currentTransaction); - const currency = CurrencyUtils.isValidCurrencyCode(selectedCurrency) ? selectedCurrency : transactionDetails?.currency; + const transactionDetails = getTransactionDetails(currentTransaction); + const currency = isValidCurrencyCode(selectedCurrency) ? selectedCurrency : transactionDetails?.currency; useFocusEffect( useCallback(() => { @@ -109,28 +99,28 @@ function IOURequestStepTaxAmountPage({ }; const updateTaxAmount = (currentAmount: CurrentMoney) => { - const taxAmountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(currentAmount.amount)); + const taxAmountInSmallestCurrencyUnits = convertToBackendAmount(Number.parseFloat(currentAmount.amount)); if (isEditingSplitBill) { - IOU.setDraftSplitTransaction(transactionID, {taxAmount: taxAmountInSmallestCurrencyUnits}); + setDraftSplitTransaction(transactionID, {taxAmount: taxAmountInSmallestCurrencyUnits}); navigateBack(); return; } if (isEditing) { - if (taxAmountInSmallestCurrencyUnits === TransactionUtils.getTaxAmount(currentTransaction, false)) { + if (taxAmountInSmallestCurrencyUnits === getTransactionTaxAmount(currentTransaction, false)) { navigateBack(); return; } - IOU.updateMoneyRequestTaxAmount(transactionID, report?.reportID ?? '', taxAmountInSmallestCurrencyUnits, policy, policyTags, policyCategories); + updateMoneyRequestTaxAmount(transactionID, report?.reportID, taxAmountInSmallestCurrencyUnits, policy, policyTags, policyCategories); navigateBack(); return; } - IOU.setMoneyRequestTaxAmount(transactionID, taxAmountInSmallestCurrencyUnits); + setMoneyRequestTaxAmount(transactionID, taxAmountInSmallestCurrencyUnits); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - IOU.setMoneyRequestCurrency(transactionID, currency || CONST.CURRENCY.USD); + setMoneyRequestCurrency(transactionID, currency || CONST.CURRENCY.USD); if (backTo) { Navigation.goBack(backTo); @@ -142,7 +132,7 @@ function IOURequestStepTaxAmountPage({ // to the confirm step. if (report?.reportID) { // TODO: Is this really needed at all? - IOU.setMoneyRequestParticipantsFromReport(transactionID, report); + setMoneyRequestParticipantsFromReport(transactionID, report); Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); return; } @@ -176,26 +166,8 @@ function IOURequestStepTaxAmountPage({ IOURequestStepTaxAmountPage.displayName = 'IOURequestStepTaxAmountPage'; -const IOURequestStepTaxAmountPageWithOnyx = withOnyx({ - splitDraftTransaction: { - key: ({route}) => { - const transactionID = route?.params.transactionID ?? 0; - return `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`; - }, - }, - policy: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '-1'}`, - }, - policyCategories: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '-1'}`, - }, - policyTags: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '-1'}`, - }, -})(IOURequestStepTaxAmountPage); - // eslint-disable-next-line rulesdir/no-negated-variables -const IOURequestStepTaxAmountPageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxAmountPageWithOnyx); +const IOURequestStepTaxAmountPageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxAmountPage); // eslint-disable-next-line rulesdir/no-negated-variables const IOURequestStepTaxAmountPageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepTaxAmountPageWithWritableReportOrNotFound); From dddeb17785dfbc6a4fb078f84c6f6a64a6acb33f Mon Sep 17 00:00:00 2001 From: war-in Date: Thu, 24 Apr 2025 14:37:21 +0200 Subject: [PATCH 3/5] migrate the rest of useRefs --- src/components/AttachmentPicker/index.native.tsx | 2 +- src/components/DeeplinkWrapper/index.website.tsx | 2 +- src/hooks/useDebounce.ts | 2 +- src/hooks/useDebounceNonReactive.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/AttachmentPicker/index.native.tsx b/src/components/AttachmentPicker/index.native.tsx index ada6b2c110f7..3db19e83978f 100644 --- a/src/components/AttachmentPicker/index.native.tsx +++ b/src/components/AttachmentPicker/index.native.tsx @@ -109,7 +109,7 @@ function AttachmentPicker({ const theme = useTheme(); const completeAttachmentSelection = useRef<(data: FileObject[]) => void>(() => {}); - const onModalHide = useRef<() => void>(); + const onModalHide = useRef<(() => void) | undefined>(undefined); const onCanceled = useRef<() => void>(() => {}); const onClosed = useRef<() => void>(() => {}); const popoverRef = useRef(null); diff --git a/src/components/DeeplinkWrapper/index.website.tsx b/src/components/DeeplinkWrapper/index.website.tsx index 91ce5e10febd..428cbc33438a 100644 --- a/src/components/DeeplinkWrapper/index.website.tsx +++ b/src/components/DeeplinkWrapper/index.website.tsx @@ -43,7 +43,7 @@ function promptToOpenInDesktopApp(initialUrl = '') { function DeeplinkWrapper({children, isAuthenticated, autoAuthState, initialUrl}: DeeplinkWrapperProps) { const [currentScreen, setCurrentScreen] = useState(); const [hasShownPrompt, setHasShownPrompt] = useState(false); - const removeListener = useRef<() => void>(); + const removeListener = useRef<(() => void) | undefined>(undefined); const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate}); const isActingAsDelegateRef = useRef(isActingAsDelegate); const delegatorEmailRef = useRef(getSearchParamFromUrl(getCurrentUrl(), 'delegatorEmail')); diff --git a/src/hooks/useDebounce.ts b/src/hooks/useDebounce.ts index 458949264ff0..b2914d86907a 100644 --- a/src/hooks/useDebounce.ts +++ b/src/hooks/useDebounce.ts @@ -21,7 +21,7 @@ type GenericFunction = (...args: any[]) => void; * @returns Returns a function to call the debounced function. */ export default function useDebounce(func: T, wait: number, options?: DebounceSettings): T { - const debouncedFnRef = useRef>(); + const debouncedFnRef = useRef | undefined>(undefined); const {leading, maxWait, trailing = true} = options ?? {}; useEffect(() => { diff --git a/src/hooks/useDebounceNonReactive.ts b/src/hooks/useDebounceNonReactive.ts index 755af694bf30..2c22658f826c 100644 --- a/src/hooks/useDebounceNonReactive.ts +++ b/src/hooks/useDebounceNonReactive.ts @@ -23,7 +23,7 @@ type GenericFunction = (...args: any[]) => void; */ export default function useDebounceNonReactive(func: T, wait: number, options?: DebounceSettings): T { const funcRef = useRef(func); // Store the latest func reference - const debouncedFnRef = useRef>(); + const debouncedFnRef = useRef | undefined>(undefined); const {leading, maxWait, trailing = true} = options ?? {}; useEffect(() => { From bfa353f6d4dd2c355c7736393976e43e04810849 Mon Sep 17 00:00:00 2001 From: war-in Date: Thu, 24 Apr 2025 15:07:40 +0200 Subject: [PATCH 4/5] migrate the rest of useRefs --- src/components/Navigation/TopLevelNavigationTabBar/index.tsx | 2 +- .../Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Navigation/TopLevelNavigationTabBar/index.tsx b/src/components/Navigation/TopLevelNavigationTabBar/index.tsx index 87f0d4f69595..503564deaa17 100644 --- a/src/components/Navigation/TopLevelNavigationTabBar/index.tsx +++ b/src/components/Navigation/TopLevelNavigationTabBar/index.tsx @@ -31,7 +31,7 @@ function TopLevelNavigationTabBar({state}: TopLevelNavigationTabBarProps) { const {shouldUseNarrowLayout} = useResponsiveLayout(); const {paddingBottom} = useSafeAreaPaddings(); const [isAfterClosingTransition, setIsAfterClosingTransition] = useState(false); - const cancelAfterInteractions = useRef | undefined>(); + const cancelAfterInteractions = useRef | undefined>(undefined); const {isBlockingViewVisible} = useContext(FullScreenBlockingViewContext); const {canUseLeftHandBar} = usePermissions(); const StyleUtils = useStyleUtils(); diff --git a/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx b/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx index 664ca9ee45f4..493814fe0c1b 100644 --- a/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx +++ b/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx @@ -21,10 +21,10 @@ type ScrollingEventData = { */ function BaseEducationalTooltip({children, shouldRender = false, shouldHideOnNavigate = true, shouldHideOnScroll = false, ...props}: EducationalTooltipProps) { const genericTooltipStateRef = useRef(undefined); - const tooltipElementRef = useRef>(); + const tooltipElementRef = useRef | undefined>(undefined); const [shouldMeasure, setShouldMeasure] = useState(false); - const show = useRef<() => void>(); + const show = useRef<(() => void) | undefined>(undefined); const navigator = useContext(NavigationContext); const insets = useSafeAreaInsets(); From 3972a76e6b5703323a8ddd64caaafb144aa94f05 Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 25 Apr 2025 18:11:28 +0200 Subject: [PATCH 5/5] revert withOnyx migration --- src/components/AddPlaidBankAccount.tsx | 30 ++++++++--- .../step/IOURequestStepTaxAmountPage.tsx | 50 +++++++++++++++---- 2 files changed, 61 insertions(+), 19 deletions(-) diff --git a/src/components/AddPlaidBankAccount.tsx b/src/components/AddPlaidBankAccount.tsx index a39c7e1e4097..e757c68b2ae4 100644 --- a/src/components/AddPlaidBankAccount.tsx +++ b/src/components/AddPlaidBankAccount.tsx @@ -1,7 +1,7 @@ import React, {useCallback, useEffect, useRef, useState} from 'react'; import {ActivityIndicator, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import {useOnyx} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useTheme from '@hooks/useTheme'; @@ -22,7 +22,15 @@ import PlaidLink from './PlaidLink'; import RadioButtons from './RadioButtons'; import Text from './Text'; -type AddPlaidBankAccountProps = { +type AddPlaidBankAccountOnyxProps = { + /** If the user has been throttled from Plaid */ + isPlaidDisabled: OnyxEntry; + + /** Plaid SDK token to use to initialize the widget */ + plaidLinkToken: OnyxEntry; +}; + +type AddPlaidBankAccountProps = AddPlaidBankAccountOnyxProps & { /** Contains plaid data */ plaidData: OnyxEntry; @@ -63,6 +71,7 @@ type AddPlaidBankAccountProps = { function AddPlaidBankAccount({ plaidData, selectedPlaidAccountID = '', + plaidLinkToken, onExitPlaid = () => {}, onSelect = () => {}, text = '', @@ -70,19 +79,16 @@ function AddPlaidBankAccount({ plaidLinkOAuthToken = '', bankAccountID = 0, allowDebit = false, + isPlaidDisabled, errorText = '', onInputChange = () => {}, isDisplayedInWalletFlow = false, }: AddPlaidBankAccountProps) { const theme = useTheme(); const styles = useThemeStyles(); - - const [plaidLinkToken] = useOnyx(ONYXKEYS.PLAID_LINK_TOKEN, {initWithStoredValues: false}); - const [isPlaidDisabled] = useOnyx(ONYXKEYS.IS_PLAID_DISABLED); - const plaidBankAccounts = plaidData?.bankAccounts ?? []; const defaultSelectedPlaidAccount = plaidBankAccounts.find((account) => account.plaidAccountID === selectedPlaidAccountID); - const defaultSelectedPlaidAccountID = defaultSelectedPlaidAccount?.plaidAccountID; + const defaultSelectedPlaidAccountID = defaultSelectedPlaidAccount?.plaidAccountID ?? '-1'; const defaultSelectedPlaidAccountMask = plaidBankAccounts.find((account) => account.plaidAccountID === selectedPlaidAccountID)?.mask ?? ''; const subscribedKeyboardShortcuts = useRef void>>([]); const previousNetworkState = useRef(undefined); @@ -281,4 +287,12 @@ function AddPlaidBankAccount({ AddPlaidBankAccount.displayName = 'AddPlaidBankAccount'; -export default AddPlaidBankAccount; +export default withOnyx({ + plaidLinkToken: { + key: ONYXKEYS.PLAID_LINK_TOKEN, + initWithStoredValues: false, + }, + isPlaidDisabled: { + key: ONYXKEYS.IS_PLAID_DISABLED, + }, +})(AddPlaidBankAccount); diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx index a2a7d8a4e491..26a2813fd065 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.tsx @@ -1,7 +1,7 @@ import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useRef} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; -import {useOnyx} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; import useLocalize from '@hooks/useLocalize'; import {setDraftSplitTransaction, setMoneyRequestCurrency, setMoneyRequestParticipantsFromReport, setMoneyRequestTaxAmount, updateMoneyRequestTaxAmount} from '@libs/actions/IOU'; @@ -15,17 +15,29 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import type {Policy, Transaction} from '@src/types/onyx'; +import type {Policy, PolicyCategories, PolicyTagLists, Transaction} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import StepScreenWrapper from './StepScreenWrapper'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; -type IOURequestStepTaxAmountPageProps = WithWritableReportOrNotFoundProps & { - transaction: OnyxEntry; +type IOURequestStepTaxAmountPageOnyxProps = { + policy: OnyxEntry; + policyCategories: OnyxEntry; + + /** Collection of tag list on a policy */ + policyTags: OnyxEntry; + + /** The draft transaction that holds data to be persisted on the current transaction */ + splitDraftTransaction: OnyxEntry; }; +type IOURequestStepTaxAmountPageProps = IOURequestStepTaxAmountPageOnyxProps & + WithWritableReportOrNotFoundProps & { + transaction: OnyxEntry; + }; + function getTaxAmount(transaction: OnyxEntry, policy: OnyxEntry, currency: string | undefined, isEditing: boolean): number | undefined { if (!transaction?.amount && !transaction?.modifiedAmount) { return; @@ -47,14 +59,12 @@ function IOURequestStepTaxAmountPage({ }, transaction, report, + policy, + policyTags, + policyCategories, + splitDraftTransaction, }: IOURequestStepTaxAmountPageProps) { const {translate} = useLocalize(); - - const [splitDraftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`); - const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`); - const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report?.policyID}`); - const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`); - const textInput = useRef(null); const isEditing = action === CONST.IOU.ACTION.EDIT; const isEditingSplitBill = isEditing && iouType === CONST.IOU.TYPE.SPLIT; @@ -166,8 +176,26 @@ function IOURequestStepTaxAmountPage({ IOURequestStepTaxAmountPage.displayName = 'IOURequestStepTaxAmountPage'; +const IOURequestStepTaxAmountPageWithOnyx = withOnyx({ + splitDraftTransaction: { + key: ({route}) => { + const transactionID = route?.params.transactionID ?? 0; + return `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`; + }, + }, + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '-1'}`, + }, + policyCategories: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '-1'}`, + }, + policyTags: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '-1'}`, + }, +})(IOURequestStepTaxAmountPage); + // eslint-disable-next-line rulesdir/no-negated-variables -const IOURequestStepTaxAmountPageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxAmountPage); +const IOURequestStepTaxAmountPageWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepTaxAmountPageWithOnyx); // eslint-disable-next-line rulesdir/no-negated-variables const IOURequestStepTaxAmountPageWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepTaxAmountPageWithWritableReportOrNotFound);