Skip to content
Merged
Show file tree
Hide file tree
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
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@
"electron-builder": "26.0.19",
"eslint": "^9.36.0",
"eslint-config-airbnb-typescript": "^18.0.0",
"eslint-config-expensify": "2.0.100",
"eslint-config-expensify": "2.0.101",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-jest": "^29.0.1",
"eslint-plugin-jsdoc": "^60.7.0",
Expand Down
7 changes: 4 additions & 3 deletions src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ MoneyRequestConfirmationList.displayName = 'MoneyRequestConfirmationList';
export default memo(
MoneyRequestConfirmationList,
(prevProps, nextProps) =>
deepEqual(prevProps.transaction, nextProps.transaction) &&
prevProps.transaction === nextProps.transaction &&
prevProps.onSendMoney === nextProps.onSendMoney &&
prevProps.onConfirm === nextProps.onConfirm &&
prevProps.iouType === nextProps.iouType &&
Expand All @@ -1224,8 +1224,9 @@ export default memo(
prevProps.isEditingSplitBill === nextProps.isEditingSplitBill &&
prevProps.iouCurrencyCode === nextProps.iouCurrencyCode &&
prevProps.iouMerchant === nextProps.iouMerchant &&
// eslint-disable-next-line rulesdir/no-deep-equal-in-memo -- selectedParticipants is derived with .map() which creates new array references
deepEqual(prevProps.selectedParticipants, nextProps.selectedParticipants) &&
deepEqual(prevProps.payeePersonalDetails, nextProps.payeePersonalDetails) &&
prevProps.payeePersonalDetails === nextProps.payeePersonalDetails &&
prevProps.isReadOnly === nextProps.isReadOnly &&
prevProps.policyID === nextProps.policyID &&
prevProps.reportID === nextProps.reportID &&
Expand All @@ -1238,6 +1239,6 @@ export default memo(
prevProps.onToggleBillable === nextProps.onToggleBillable &&
prevProps.hasSmartScanFailed === nextProps.hasSmartScanFailed &&
prevProps.reportActionID === nextProps.reportActionID &&
deepEqual(prevProps.action, nextProps.action) &&
prevProps.action === nextProps.action &&
prevProps.shouldDisplayReceipt === nextProps.shouldDisplayReceipt,
);
9 changes: 5 additions & 4 deletions src/components/MoneyRequestConfirmationListFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,7 @@ MoneyRequestConfirmationListFooter.displayName = 'MoneyRequestConfirmationListFo
export default memo(
MoneyRequestConfirmationListFooter,
(prevProps, nextProps) =>
deepEqual(prevProps.action, nextProps.action) &&
prevProps.action === nextProps.action &&
prevProps.currency === nextProps.currency &&
prevProps.didConfirm === nextProps.didConfirm &&
prevProps.distance === nextProps.distance &&
Expand All @@ -1093,21 +1093,22 @@ export default memo(
prevProps.isReadOnly === nextProps.isReadOnly &&
prevProps.isTypeInvoice === nextProps.isTypeInvoice &&
prevProps.onToggleBillable === nextProps.onToggleBillable &&
deepEqual(prevProps.policy, nextProps.policy) &&
deepEqual(prevProps.policyTagLists, nextProps.policyTagLists) &&
prevProps.policy === nextProps.policy &&
prevProps.policyTagLists === nextProps.policyTagLists &&
prevProps.rate === nextProps.rate &&
prevProps.receiptFilename === nextProps.receiptFilename &&
prevProps.receiptPath === nextProps.receiptPath &&
prevProps.reportActionID === nextProps.reportActionID &&
prevProps.reportID === nextProps.reportID &&
// eslint-disable-next-line rulesdir/no-deep-equal-in-memo -- selectedParticipants is derived with .map() which creates new array references
deepEqual(prevProps.selectedParticipants, nextProps.selectedParticipants) &&
prevProps.shouldDisplayFieldError === nextProps.shouldDisplayFieldError &&
prevProps.shouldDisplayReceipt === nextProps.shouldDisplayReceipt &&
prevProps.shouldShowCategories === nextProps.shouldShowCategories &&
prevProps.shouldShowMerchant === nextProps.shouldShowMerchant &&
prevProps.shouldShowSmartScanFields === nextProps.shouldShowSmartScanFields &&
prevProps.shouldShowTax === nextProps.shouldShowTax &&
deepEqual(prevProps.transaction, nextProps.transaction) &&
prevProps.transaction === nextProps.transaction &&
prevProps.transactionID === nextProps.transactionID &&
prevProps.unit === nextProps.unit,
);
11 changes: 7 additions & 4 deletions src/components/OptionRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {deepEqual} from 'fast-equals';
import React, {useEffect, useRef, useState} from 'react';
import type {StyleProp, TextStyle, ViewStyle} from 'react-native';
import {InteractionManager, StyleSheet, View} from 'react-native';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
Expand All @@ -14,7 +15,6 @@ import Button from './Button';
import DisplayNames from './DisplayNames';
import Hoverable from './Hoverable';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
import MoneyRequestAmountInput from './MoneyRequestAmountInput';
import OfflineWithFeedback from './OfflineWithFeedback';
import PressableWithFeedback from './Pressable/PressableWithFeedback';
Expand Down Expand Up @@ -112,6 +112,7 @@ function OptionRow({
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {translate, localeCompare} = useLocalize();
const icons = useMemoizedLazyExpensifyIcons(['DotIndicator', 'Checkmark'] as const);
const pressableRef = useRef<View | HTMLDivElement>(null);
const [isDisabled, setIsDisabled] = useState(isOptionDisabled);

Expand Down Expand Up @@ -282,15 +283,15 @@ function OptionRow({
{!isSelected && option.brickRoadIndicator === CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR && (
<View style={[styles.alignItemsCenter, styles.justifyContentCenter]}>
<Icon
src={Expensicons.DotIndicator}
src={icons.DotIndicator}
fill={theme.danger}
/>
</View>
)}
{!isSelected && option.brickRoadIndicator === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO && (
<View style={[styles.alignItemsCenter, styles.justifyContentCenter]}>
<Icon
src={Expensicons.DotIndicator}
src={icons.DotIndicator}
fill={theme.iconSuccessFill}
/>
</View>
Expand Down Expand Up @@ -321,7 +322,7 @@ function OptionRow({
{isSelected && highlightSelected && (
<View style={styles.defaultCheckmarkWrapper}>
<Icon
src={Expensicons.Checkmark}
src={icons.Checkmark}
fill={theme.iconSuccessFill}
/>
</View>
Expand Down Expand Up @@ -361,6 +362,7 @@ export default React.memo(
prevProps.showSelectedState === nextProps.showSelectedState &&
prevProps.highlightSelected === nextProps.highlightSelected &&
prevProps.showTitleTooltip === nextProps.showTitleTooltip &&
// eslint-disable-next-line rulesdir/no-deep-equal-in-memo -- icons array is created inline in some usages (e.g., BaseReactionList) with unstable references
deepEqual(prevProps.option.icons, nextProps.option.icons) &&
prevProps.optionIsFocused === nextProps.optionIsFocused &&
prevProps.option.text === nextProps.option.text &&
Expand All @@ -373,6 +375,7 @@ export default React.memo(
prevProps.option.pendingAction === nextProps.option.pendingAction &&
prevProps.option.customIcon === nextProps.option.customIcon &&
prevProps.option.tabIndex === nextProps.option.tabIndex &&
// eslint-disable-next-line rulesdir/no-deep-equal-in-memo -- amountInputProps origin and reference stability cannot be determined across all usages
deepEqual(prevProps.option.amountInputProps, nextProps.option.amountInputProps),
);

Expand Down
3 changes: 3 additions & 0 deletions src/components/PopoverMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -588,12 +588,15 @@ PopoverMenu.displayName = 'PopoverMenu';
export default React.memo(
PopoverMenu,
(prevProps, nextProps) =>
// eslint-disable-next-line rulesdir/no-deep-equal-in-memo -- menuItems array is created inline in most usages with unstable references
deepEqual(prevProps.menuItems, nextProps.menuItems) &&
prevProps.isVisible === nextProps.isVisible &&
// eslint-disable-next-line rulesdir/no-deep-equal-in-memo -- anchorPosition object is created inline in most usages
deepEqual(prevProps.anchorPosition, nextProps.anchorPosition) &&
prevProps.anchorRef === nextProps.anchorRef &&
prevProps.headerText === nextProps.headerText &&
prevProps.fromSidebarMediumScreen === nextProps.fromSidebarMediumScreen &&
// eslint-disable-next-line rulesdir/no-deep-equal-in-memo -- anchorAlignment object is created inline in most usages
deepEqual(prevProps.anchorAlignment, nextProps.anchorAlignment) &&
prevProps.animationIn === nextProps.animationIn &&
prevProps.animationOut === nextProps.animationOut &&
Expand Down
1 change: 1 addition & 0 deletions src/pages/home/ReportScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1041,4 +1041,5 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
}

ReportScreen.displayName = 'ReportScreen';
// eslint-disable-next-line rulesdir/no-deep-equal-in-memo
export default memo(ReportScreen, (prevProps, nextProps) => deepEqual(prevProps.route, nextProps.route));
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@
const isTryNewDotNVPDismissed = !!tryNewDot?.classicRedirect?.dismissed;

const isMoneyRequest = useMemo(() => ReportUtilsIsMoneyRequest(childReport), [childReport]);
const isTrackExpenseReport = ReportUtilsIsTrackExpenseReport(childReport);

Check failure on line 239 in src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

`ReportUtilsIsTrackExpenseReport` is deprecated. Use isTrackExpenseReportNew function instead
const isSingleTransactionView = isMoneyRequest || isTrackExpenseReport;
const isMoneyRequestOrReport = isMoneyRequestReport || isSingleTransactionView;

Expand Down Expand Up @@ -454,6 +454,7 @@
);
}

// eslint-disable-next-line rulesdir/no-deep-equal-in-memo
export default memo(BaseReportActionContextMenu, deepEqual);

export type {BaseReportActionContextMenuProps};
1 change: 1 addition & 0 deletions src/pages/home/report/PureReportActionItem.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable rulesdir/no-deep-equal-in-memo */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why disable the rule at the beginning of the file? Thank you.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Otherwise, we'd need to disable in multiple lines. Let me know what is the recommended approach here, thanks!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think ideally we disable it in the lines individually as then nobody will be forced to observe this rule in this file after that

import {deepEqual} from 'fast-equals';
import mapValues from 'lodash/mapValues';
import React, {memo, use, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
Expand Down
5 changes: 2 additions & 3 deletions src/pages/home/report/ReportActionItemContentCreated.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {deepEqual} from 'fast-equals';
import React, {memo, useMemo} from 'react';
import {View} from 'react-native';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
Expand Down Expand Up @@ -216,8 +215,8 @@ ReportActionItemContentCreated.displayName = 'ReportActionItemContentCreated';
export default memo(
ReportActionItemContentCreated,
(prevProps, nextProps) =>
deepEqual(prevProps.contextValue, nextProps.contextValue) &&
deepEqual(prevProps.parentReportAction, nextProps.parentReportAction) &&
prevProps.contextValue === nextProps.contextValue &&
prevProps.parentReportAction === nextProps.parentReportAction &&
prevProps.transactionID === nextProps.transactionID &&
prevProps.draftMessage === nextProps.draftMessage &&
prevProps.shouldHideThreadDividerLine === nextProps.shouldHideThreadDividerLine,
Expand Down
15 changes: 9 additions & 6 deletions src/pages/home/report/ReportFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {isBlockedFromChatSelector} from '@selectors/BlockedFromChat';
import {Str} from 'expensify-common';
import {deepEqual} from 'fast-equals';
import React, {memo, useCallback, useEffect, useState} from 'react';
import {Keyboard, View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
Expand Down Expand Up @@ -267,12 +266,16 @@ ReportFooter.displayName = 'ReportFooter';
export default memo(
ReportFooter,
(prevProps, nextProps) =>
deepEqual(prevProps.report, nextProps.report) &&
// Report comes from useOnyx - reference is stable
prevProps.report === nextProps.report &&
prevProps.pendingAction === nextProps.pendingAction &&
prevProps.isComposerFullSize === nextProps.isComposerFullSize &&
prevProps.lastReportAction === nextProps.lastReportAction &&
deepEqual(prevProps.reportMetadata, nextProps.reportMetadata) &&
deepEqual(prevProps.policy?.employeeList, nextProps.policy?.employeeList) &&
deepEqual(prevProps.policy?.role, nextProps.policy?.role) &&
deepEqual(prevProps.reportTransactions, nextProps.reportTransactions),
// reportMetadata comes from useOnyx - reference is stable
prevProps.reportMetadata === nextProps.reportMetadata &&
// policy comes from useOnyx - comparing nested properties which may be stable
prevProps.policy?.employeeList === nextProps.policy?.employeeList &&
prevProps.policy?.role === nextProps.policy?.role &&
// reportTransactions comes from useOnyx - reference is stable
prevProps.reportTransactions === nextProps.reportTransactions,
);
1 change: 1 addition & 0 deletions src/pages/iou/request/MoneyRequestAttendeeSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -313,4 +313,5 @@ function MoneyRequestAttendeeSelector({attendees = [], onFinish, onAttendeesAdde

MoneyRequestAttendeeSelector.displayName = 'MoneyRequestAttendeeSelector';

// eslint-disable-next-line rulesdir/no-deep-equal-in-memo -- attendees array is derived and may have unstable references
export default memo(MoneyRequestAttendeeSelector, (prevProps, nextProps) => deepEqual(prevProps.attendees, nextProps.attendees) && prevProps.iouType === nextProps.iouType);
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@ MoneyRequestParticipantsSelector.displayName = 'MoneyRequestParticipantsSelector
export default memo(
MoneyRequestParticipantsSelector,
(prevProps, nextProps) =>
// eslint-disable-next-line rulesdir/no-deep-equal-in-memo
deepEqual(prevProps.participants, nextProps.participants) &&
prevProps.iouType === nextProps.iouType &&
prevProps.isWorkspacesOnly === nextProps.isWorkspacesOnly &&
Expand Down
Loading