Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 62 additions & 14 deletions src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import Log from '@libs/Log';
import {validateAmount} from '@libs/MoneyRequestUtils';
import Navigation from '@libs/Navigation/Navigation';
import {getIOUConfirmationOptionsFromPayeePersonalDetail, hasEnabledOptions} from '@libs/OptionsListUtils';
import {getTagLists, isTaxTrackingEnabled} from '@libs/PolicyUtils';
import {getDistanceRateCustomUnitRate, getTagLists, isTaxTrackingEnabled} from '@libs/PolicyUtils';
import {isSelectedManagerMcTest} from '@libs/ReportUtils';
import type {OptionData} from '@libs/ReportUtils';
import {
Expand Down Expand Up @@ -332,14 +332,27 @@ function MoneyRequestConfirmationList({

const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, isDistanceRequest, isPerDiemRequest);

// Update the tax code when the default changes (for example, because the transaction currency changed)
const defaultTaxCode = getDefaultTaxCode(policy, transaction) ?? '';
const previousTransactionAmount = usePrevious(transaction?.amount);
const previousTransactionCurrency = usePrevious(transaction?.currency);
const previousTransactionModifiedCurrency = usePrevious(transaction?.modifiedCurrency);
const previousCustomUnitRateID = usePrevious(customUnitRateID);
useEffect(() => {
if (!transactionID) {
// previousTransaction is in the condition because if it is falsy, it means this is the first time the useEffect is triggered after we load it, so we should calculate the default
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ PERF-6 (docs)

Passing entire objects as dependencies causes hooks to re-execute whenever any property changes, even unrelated ones. Specifying individual properties creates more granular dependency tracking, reducing unnecessary hook executions and improving performance predictability.

Consider replacing policy in the dependency array with specific policy properties that are actually used in the effect. Based on the getDefaultTaxCode function call, you likely only need:

}, [customUnitRateID, policy?.id, previousCustomUnitRateID, previousTransactionCurrency, previousTransactionModifiedCurrency, shouldShowTax, transaction?.transactionID, transaction?.taxCode, transaction?.modifiedCurrency, transaction?.currency, transactionID]);

// tax even if the other parameters are the same against their previous values.
if (
!shouldShowTax ||
!transaction ||
!transactionID ||
(transaction.taxCode &&
previousTransactionModifiedCurrency === transaction.modifiedCurrency &&
previousTransactionCurrency === transaction.currency &&
previousCustomUnitRateID === customUnitRateID)
) {
return;
}
setMoneyRequestTaxRate(transactionID, defaultTaxCode);
}, [defaultTaxCode, transactionID]);
const defaultTaxCode = getDefaultTaxCode(policy, transaction);
setMoneyRequestTaxRate(transactionID, defaultTaxCode ?? '');
}, [customUnitRateID, policy, previousCustomUnitRateID, previousTransactionCurrency, previousTransactionModifiedCurrency, shouldShowTax, transaction, transactionID]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ PERF-6 (docs)

Passing entire objects as dependencies causes hooks to re-execute whenever any property changes, even unrelated ones. Specifying individual properties creates more granular dependency tracking, reducing unnecessary hook executions and improving performance predictability.

Consider replacing transaction in the dependency array with specific transaction properties that are actually used in the effect:

}, [customUnitRateID, policy, previousCustomUnitRateID, previousTransactionCurrency, previousTransactionModifiedCurrency, shouldShowTax, transaction?.transactionID, transaction?.taxCode, transaction?.modifiedCurrency, transaction?.currency, transactionID]);


const isMovingTransactionFromTrackExpense = isMovingTransactionFromTrackExpenseUtil(action);

Expand Down Expand Up @@ -474,17 +487,53 @@ function MoneyRequestConfirmationList({
}
}, [shouldCalculateDistanceAmount, isReadOnly, distanceRequestAmount, transactionID, currency, isTypeSplit, isPolicyExpenseChat, selectedParticipantsProp, transaction]);

const previousTaxCode = usePrevious(transaction?.taxCode);

// Calculate and set tax amount in transaction draft
const taxableAmount = isDistanceRequest ? DistanceRequestUtils.getTaxableAmount(policy, customUnitRateID, distance) : (transaction?.amount ?? 0);
const taxPercentage = getTaxValue(policy, transaction, transaction?.taxCode ?? defaultTaxCode) ?? '';
const taxAmount = calculateTaxAmount(taxPercentage, taxableAmount, transaction?.currency ?? CONST.CURRENCY.USD);
const taxAmountInSmallestCurrencyUnits = convertToBackendAmount(Number.parseFloat(taxAmount.toString()));
useEffect(() => {
if (!transactionID) {
if (
!shouldShowTax ||
!transaction ||
(transaction.taxAmount !== undefined &&
previousTransactionAmount === transaction.amount &&
previousTransactionCurrency === transaction.currency &&
previousCustomUnitRateID === customUnitRateID &&
previousTaxCode === transaction.taxCode)
) {
return;
}
setMoneyRequestTaxAmount(transactionID, taxAmountInSmallestCurrencyUnits);
}, [transactionID, taxAmountInSmallestCurrencyUnits]);

let taxableAmount: number | undefined;
let taxCode: string | undefined;
if (isDistanceRequest) {
if (customUnitRateID) {
const customUnitRate = getDistanceRateCustomUnitRate(policy, customUnitRateID);
taxCode = customUnitRate?.attributes?.taxRateExternalID;
taxableAmount = DistanceRequestUtils.getTaxableAmount(policy, customUnitRateID, distance);
}
} else {
taxableAmount = transaction.amount ?? 0;
taxCode = transaction.taxCode ?? getDefaultTaxCode(policy, transaction) ?? '';
}

if (taxCode && taxableAmount) {
const taxPercentage = getTaxValue(policy, transaction, taxCode) ?? '';
const taxAmount = calculateTaxAmount(taxPercentage, taxableAmount, transaction.currency);
const taxAmountInSmallestCurrencyUnits = convertToBackendAmount(Number.parseFloat(taxAmount.toString()));
setMoneyRequestTaxAmount(transaction.transactionID, taxAmountInSmallestCurrencyUnits);
}
}, [
policy,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ PERF-6 (docs)

Passing entire objects as dependencies causes hooks to re-execute whenever any property changes, even unrelated ones. Specifying individual properties creates more granular dependency tracking, reducing unnecessary hook executions and improving performance predictability.

Consider replacing policy in the dependency array with specific policy properties that are actually used in the effect. Based on the effect logic, you likely only need:

}, [
    policy?.id,
    // ... other dependencies
]);

shouldShowTax,
previousTransactionAmount,
previousTransactionCurrency,
transaction,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ PERF-6 (docs)

Passing entire objects as dependencies causes hooks to re-execute whenever any property changes, even unrelated ones. Specifying individual properties creates more granular dependency tracking, reducing unnecessary hook executions and improving performance predictability.

Consider replacing transaction in the dependency array with specific transaction properties that are actually used in the effect:

}, [
    policy,
    shouldShowTax,
    previousTransactionAmount,
    previousTransactionCurrency,
    transaction?.transactionID,
    transaction?.taxCode,
    transaction?.amount,
    transaction?.currency,
    transaction?.taxAmount,
    isDistanceRequest,
    customUnitRateID,
    previousCustomUnitRateID,
    previousTaxCode,
    distance,
]);

isDistanceRequest,
customUnitRateID,
previousCustomUnitRateID,
previousTaxCode,
distance,
]);

// If completing a split expense fails, set didConfirm to false to allow the user to edit the fields again
if (isEditingSplitBill && didConfirm) {
Expand Down Expand Up @@ -945,7 +994,6 @@ function MoneyRequestConfirmationList({
routeError,
isDelegateAccessRestricted,
showDelegateNoAccessModal,
setDidConfirmSplit,
],
);

Expand Down
Loading