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
9 changes: 9 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ const restrictedImportPaths = [
importNames: ['memoize'],
message: "Please use '@src/libs/memoize' instead.",
},
{
name: 'lodash/isEqual',
message: "Please use 'deepEqual' from 'fast-equals' instead.",
},
{
name: 'lodash',
importNames: ['isEqual'],
message: "Please use 'deepEqual' from 'fast-equals' instead.",
},
{
name: 'react-native-animatable',
message: "Please use 'react-native-reanimated' instead.",
Expand Down
4 changes: 2 additions & 2 deletions src/components/Attachments/AttachmentCarousel/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import isEqual from 'lodash/isEqual';
import {deepEqual} from 'fast-equals';
import type {MutableRefObject} from 'react';
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import type {ListRenderItemInfo} from 'react-native';
Expand Down Expand Up @@ -100,7 +100,7 @@ function AttachmentCarousel({report, attachmentID, source, onNavigate, setDownlo
newAttachments = extractAttachments(CONST.ATTACHMENT_TYPE.REPORT, {parentReportAction, reportActions: reportActions ?? undefined, report});
}

if (isEqual(attachments, newAttachments)) {
if (deepEqual(attachments, newAttachments)) {
if (attachments.length === 0) {
setPage(-1);
setDownloadButtonVisibility?.(false);
Expand Down
4 changes: 2 additions & 2 deletions src/components/Form/FormProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useFocusEffect} from '@react-navigation/native';
import lodashIsEqual from 'lodash/isEqual';
import {deepEqual} from 'fast-equals';
import type {ForwardedRef, MutableRefObject, ReactNode, RefAttributes} from 'react';
import React, {createRef, forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react';
import {InteractionManager} from 'react-native';
Expand Down Expand Up @@ -194,7 +194,7 @@ function FormProvider(

const touchedInputErrors = Object.fromEntries(Object.entries(validateErrors).filter(([inputID]) => touchedInputs.current[inputID]));

if (!lodashIsEqual(errors, touchedInputErrors)) {
if (!deepEqual(errors, touchedInputErrors)) {
setErrors(touchedInputErrors);
}

Expand Down
10 changes: 5 additions & 5 deletions src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useFocusEffect, useIsFocused} from '@react-navigation/native';
import lodashIsEqual from 'lodash/isEqual';
import {deepEqual} from 'fast-equals';
import React, {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {InteractionManager, View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
Expand Down Expand Up @@ -1113,7 +1113,7 @@ MoneyRequestConfirmationList.displayName = 'MoneyRequestConfirmationList';
export default memo(
MoneyRequestConfirmationList,
(prevProps, nextProps) =>
lodashIsEqual(prevProps.transaction, nextProps.transaction) &&
deepEqual(prevProps.transaction, nextProps.transaction) &&
prevProps.onSendMoney === nextProps.onSendMoney &&
prevProps.onConfirm === nextProps.onConfirm &&
prevProps.iouType === nextProps.iouType &&
Expand All @@ -1125,8 +1125,8 @@ export default memo(
prevProps.isEditingSplitBill === nextProps.isEditingSplitBill &&
prevProps.iouCurrencyCode === nextProps.iouCurrencyCode &&
prevProps.iouMerchant === nextProps.iouMerchant &&
lodashIsEqual(prevProps.selectedParticipants, nextProps.selectedParticipants) &&
lodashIsEqual(prevProps.payeePersonalDetails, nextProps.payeePersonalDetails) &&
deepEqual(prevProps.selectedParticipants, nextProps.selectedParticipants) &&
deepEqual(prevProps.payeePersonalDetails, nextProps.payeePersonalDetails) &&
prevProps.isReadOnly === nextProps.isReadOnly &&
prevProps.bankAccountRoute === nextProps.bankAccountRoute &&
prevProps.policyID === nextProps.policyID &&
Expand All @@ -1140,6 +1140,6 @@ export default memo(
prevProps.onToggleBillable === nextProps.onToggleBillable &&
prevProps.hasSmartScanFailed === nextProps.hasSmartScanFailed &&
prevProps.reportActionID === nextProps.reportActionID &&
lodashIsEqual(prevProps.action, nextProps.action) &&
deepEqual(prevProps.action, nextProps.action) &&
prevProps.shouldDisplayReceipt === nextProps.shouldDisplayReceipt,
);
12 changes: 6 additions & 6 deletions src/components/MoneyRequestConfirmationListFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {format} from 'date-fns';
import {Str} from 'expensify-common';
import lodashIsEqual from 'lodash/isEqual';
import {deepEqual} from 'fast-equals';
import React, {memo, useMemo} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
Expand Down Expand Up @@ -904,7 +904,7 @@ MoneyRequestConfirmationListFooter.displayName = 'MoneyRequestConfirmationListFo
export default memo(
MoneyRequestConfirmationListFooter,
(prevProps, nextProps) =>
lodashIsEqual(prevProps.action, nextProps.action) &&
deepEqual(prevProps.action, nextProps.action) &&
prevProps.currency === nextProps.currency &&
prevProps.didConfirm === nextProps.didConfirm &&
prevProps.distance === nextProps.distance &&
Expand All @@ -926,21 +926,21 @@ export default memo(
prevProps.isReadOnly === nextProps.isReadOnly &&
prevProps.isTypeInvoice === nextProps.isTypeInvoice &&
prevProps.onToggleBillable === nextProps.onToggleBillable &&
lodashIsEqual(prevProps.policy, nextProps.policy) &&
lodashIsEqual(prevProps.policyTagLists, nextProps.policyTagLists) &&
deepEqual(prevProps.policy, nextProps.policy) &&
deepEqual(prevProps.policyTagLists, nextProps.policyTagLists) &&
prevProps.rate === nextProps.rate &&
prevProps.receiptFilename === nextProps.receiptFilename &&
prevProps.receiptPath === nextProps.receiptPath &&
prevProps.reportActionID === nextProps.reportActionID &&
prevProps.reportID === nextProps.reportID &&
lodashIsEqual(prevProps.selectedParticipants, nextProps.selectedParticipants) &&
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 &&
lodashIsEqual(prevProps.transaction, nextProps.transaction) &&
deepEqual(prevProps.transaction, nextProps.transaction) &&
prevProps.transactionID === nextProps.transactionID &&
prevProps.unit === nextProps.unit,
);
14 changes: 7 additions & 7 deletions src/components/OptionRow.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import lodashIsEqual from 'lodash/isEqual';
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 useLocalize from '@hooks/useLocalize';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
import {shouldOptionShowTooltip} from '@libs/OptionsListUtils';
import {getDisplayNamesWithTooltips} from '@libs/ReportUtils';
import type {OptionData} from '@libs/ReportUtils';
import CONST from '@src/CONST';
import Button from './Button';
Expand Down Expand Up @@ -149,7 +149,7 @@ function OptionRow({
const firstIcon = option?.icons?.at(0);

// We only create tooltips for the first 10 users or so since some reports have hundreds of users, causing performance to degrade.
const displayNamesWithTooltips = ReportUtils.getDisplayNamesWithTooltips((option.participantsList ?? (option.accountID ? [option] : [])).slice(0, 10), shouldUseShortFormInTooltip);
const displayNamesWithTooltips = getDisplayNamesWithTooltips((option.participantsList ?? (option.accountID ? [option] : [])).slice(0, 10), shouldUseShortFormInTooltip);
let subscriptColor = theme.appBG;
if (optionIsFocused) {
subscriptColor = focusedBackgroundColor;
Expand Down Expand Up @@ -221,7 +221,7 @@ function OptionRow({
icons={option.icons}
size={CONST.AVATAR_SIZE.DEFAULT}
secondAvatarStyle={[StyleUtils.getBackgroundAndBorderStyle(hovered && !optionIsFocused ? hoveredBackgroundColor : subscriptColor)]}
shouldShowTooltip={showTitleTooltip && OptionsListUtils.shouldOptionShowTooltip(option)}
shouldShowTooltip={showTitleTooltip && shouldOptionShowTooltip(option)}
/>
))}
<View style={contentContainerStyles}>
Expand Down Expand Up @@ -358,7 +358,7 @@ export default React.memo(
prevProps.showSelectedState === nextProps.showSelectedState &&
prevProps.highlightSelected === nextProps.highlightSelected &&
prevProps.showTitleTooltip === nextProps.showTitleTooltip &&
lodashIsEqual(prevProps.option.icons, nextProps.option.icons) &&
deepEqual(prevProps.option.icons, nextProps.option.icons) &&
prevProps.optionIsFocused === nextProps.optionIsFocused &&
prevProps.option.text === nextProps.option.text &&
prevProps.option.alternateText === nextProps.option.alternateText &&
Expand All @@ -370,7 +370,7 @@ export default React.memo(
prevProps.option.pendingAction === nextProps.option.pendingAction &&
prevProps.option.customIcon === nextProps.option.customIcon &&
prevProps.option.tabIndex === nextProps.option.tabIndex &&
lodashIsEqual(prevProps.option.amountInputProps, nextProps.option.amountInputProps),
deepEqual(prevProps.option.amountInputProps, nextProps.option.amountInputProps),
);

export type {OptionRowProps};
8 changes: 4 additions & 4 deletions src/components/PopoverMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable react/jsx-props-no-spreading */
import lodashIsEqual from 'lodash/isEqual';
import {deepEqual} from 'fast-equals';
import type {ReactNode, RefObject} from 'react';
import React, {useCallback, useLayoutEffect, useMemo, useState} from 'react';
import {StyleSheet, View} from 'react-native';
Expand Down Expand Up @@ -443,13 +443,13 @@ PopoverMenu.displayName = 'PopoverMenu';
export default React.memo(
PopoverMenu,
(prevProps, nextProps) =>
lodashIsEqual(prevProps.menuItems, nextProps.menuItems) &&
deepEqual(prevProps.menuItems, nextProps.menuItems) &&
prevProps.isVisible === nextProps.isVisible &&
lodashIsEqual(prevProps.anchorPosition, nextProps.anchorPosition) &&
deepEqual(prevProps.anchorPosition, nextProps.anchorPosition) &&
prevProps.anchorRef === nextProps.anchorRef &&
prevProps.headerText === nextProps.headerText &&
prevProps.fromSidebarMediumScreen === nextProps.fromSidebarMediumScreen &&
lodashIsEqual(prevProps.anchorAlignment, nextProps.anchorAlignment) &&
deepEqual(prevProps.anchorAlignment, nextProps.anchorAlignment) &&
prevProps.animationIn === nextProps.animationIn &&
prevProps.animationOut === nextProps.animationOut &&
prevProps.animationInTiming === nextProps.animationInTiming &&
Expand Down
8 changes: 4 additions & 4 deletions src/components/PopoverWithMeasuredContent.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import isEqual from 'lodash/isEqual';
import {circularDeepEqual, deepEqual} from 'fast-equals';
import React, {useContext, useMemo, useState} from 'react';
import type {LayoutChangeEvent} from 'react-native';
import {View} from 'react-native';
Expand Down Expand Up @@ -90,8 +90,8 @@ function PopoverWithMeasuredContent({

if (!prevIsVisible && isVisible && isContentMeasured && !shouldSkipRemeasurement) {
// Check if anything significant changed that would require re-measurement
const hasAnchorPositionChanged = !isEqual(prevAnchorPosition, anchorPosition);
const hasWindowSizeChanged = !isEqual(prevWindowDimensions, {windowWidth, windowHeight});
const hasAnchorPositionChanged = !deepEqual(prevAnchorPosition, anchorPosition);
const hasWindowSizeChanged = !deepEqual(prevWindowDimensions, {windowWidth, windowHeight});
const hasStaticDimensions = popoverDimensions.width > 0 && popoverDimensions.height > 0;

// Only reset if:
Expand Down Expand Up @@ -238,7 +238,7 @@ export default React.memo(PopoverWithMeasuredContent, (prevProps, nextProps) =>
if (prevProps.isVisible === nextProps.isVisible && nextProps.isVisible === false) {
return true;
}
return isEqual(prevProps, nextProps);
return circularDeepEqual(prevProps, nextProps);
});

export type {PopoverWithMeasuredContentProps};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {useIsFocused} from '@react-navigation/native';
import {deepEqual} from 'fast-equals';
import isEmpty from 'lodash/isEmpty';
import isEqual from 'lodash/isEqual';
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
Expand Down Expand Up @@ -155,7 +155,7 @@ function SearchPageHeaderInput({queryJSON, searchRouterListVisible, hideSearchRo
setAutocompleteQueryValue(updatedUserQuery);

const updatedSubstitutionsMap = getUpdatedSubstitutionsMap(singleLineUserQuery, autocompleteSubstitutions);
if (!isEqual(autocompleteSubstitutions, updatedSubstitutionsMap) && !isEmpty(updatedSubstitutionsMap)) {
if (!deepEqual(autocompleteSubstitutions, updatedSubstitutionsMap) && !isEmpty(updatedSubstitutionsMap)) {
setAutocompleteSubstitutions(updatedSubstitutionsMap);
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/Search/SearchRouter/SearchRouter.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {findFocusedRoute, useNavigationState} from '@react-navigation/native';
import isEqual from 'lodash/isEqual';
import {deepEqual} from 'fast-equals';
import React, {forwardRef, useCallback, useEffect, useRef, useState} from 'react';
import type {TextInputProps} from 'react-native';
import {InteractionManager, Keyboard, View} from 'react-native';
Expand Down Expand Up @@ -198,7 +198,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
setAutocompleteQueryValue(updatedUserQuery);

const updatedSubstitutionsMap = getUpdatedSubstitutionsMap(singleLineUserQuery, autocompleteSubstitutions);
if (!isEqual(autocompleteSubstitutions, updatedSubstitutionsMap)) {
if (!deepEqual(autocompleteSubstitutions, updatedSubstitutionsMap)) {
setAutocompleteSubstitutions(updatedSubstitutionsMap);
}

Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useDeepCompareRef.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import isEqual from 'lodash/isEqual';
import {deepEqual} from 'fast-equals';
import {useRef} from 'react';

/**
Expand All @@ -18,7 +18,7 @@ import {useRef} from 'react';
export default function useDeepCompareRef<T>(value: T): T | undefined {
const ref = useRef<T | undefined>(undefined);
// eslint-disable-next-line react-compiler/react-compiler
if (!isEqual(value, ref.current)) {
if (!deepEqual(value, ref.current)) {
// eslint-disable-next-line react-compiler/react-compiler
ref.current = value;
}
Expand Down
16 changes: 8 additions & 8 deletions src/hooks/useFetchRoute.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import isEqual from 'lodash/isEqual';
import {deepEqual} from 'fast-equals';
import {useEffect} from 'react';
import type {OnyxEntry} from 'react-native-onyx';
import * as TransactionUtils from '@libs/TransactionUtils';
import * as TransactionAction from '@userActions/Transaction';
import {getRoute} from '@libs/actions/Transaction';
import {getValidWaypoints, hasRoute as hasRouteTransactionUtils, isDistanceRequest as isDistanceRequestTransactionUtils} from '@libs/TransactionUtils';
import type {IOUAction} from '@src/CONST';
import CONST from '@src/CONST';
import type {Transaction} from '@src/types/onyx';
Expand All @@ -19,21 +19,21 @@ export default function useFetchRoute(
) {
const {isOffline} = useNetwork();
const hasRouteError = !!transaction?.errorFields?.route;
const hasRoute = TransactionUtils.hasRoute(transaction);
const hasRoute = hasRouteTransactionUtils(transaction);
const isRouteAbsentWithoutErrors = !hasRoute && !hasRouteError;
const isLoadingRoute = transaction?.comment?.isLoading ?? false;
const validatedWaypoints = TransactionUtils.getValidWaypoints(waypoints);
const validatedWaypoints = getValidWaypoints(waypoints);
const previousValidatedWaypoints = usePrevious(validatedWaypoints);
const haveValidatedWaypointsChanged = !isEqual(previousValidatedWaypoints, validatedWaypoints);
const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction);
const haveValidatedWaypointsChanged = !deepEqual(previousValidatedWaypoints, validatedWaypoints);
const isDistanceRequest = isDistanceRequestTransactionUtils(transaction);
const shouldFetchRoute = isDistanceRequest && (isRouteAbsentWithoutErrors || haveValidatedWaypointsChanged) && !isLoadingRoute && Object.keys(validatedWaypoints).length > 1;

useEffect(() => {
if (isOffline || !shouldFetchRoute || !transaction?.transactionID) {
return;
}

TransactionAction.getRoute(transaction.transactionID, validatedWaypoints, transactionState);
getRoute(transaction.transactionID, validatedWaypoints, transactionState);
}, [shouldFetchRoute, transaction?.transactionID, validatedWaypoints, isOffline, action, transactionState]);

return {shouldFetchRoute, validatedWaypoints};
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/useSearchHighlightAndScroll.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useIsFocused} from '@react-navigation/native';
import isEqual from 'lodash/isEqual';
import {deepEqual} from 'fast-equals';
import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import type {SearchQueryJSON} from '@components/Search/types';
Expand Down Expand Up @@ -61,8 +61,8 @@ function useSearchHighlightAndScroll({searchResults, transactions, previousTrans
return;
}

const hasTransactionsIDsChange = !isEqual(transactionsIDs, previousTransactionsIDs);
const hasReportActionsIDsChange = !isEqual(reportActionsIDs, previousReportActionsIDs);
const hasTransactionsIDsChange = !deepEqual(transactionsIDs, previousTransactionsIDs);
const hasReportActionsIDsChange = !deepEqual(reportActionsIDs, previousReportActionsIDs);

// Check if there is a change in the transactions or report actions list
if ((!isChat && hasTransactionsIDsChange) || hasReportActionsIDsChange) {
Expand Down
4 changes: 2 additions & 2 deletions src/libs/Performance.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import isEqual from 'lodash/isEqual';
import {deepEqual} from 'fast-equals';
import isObject from 'lodash/isObject';
import lodashTransform from 'lodash/transform';
import React, {forwardRef, Profiler} from 'react';
Expand All @@ -17,7 +17,7 @@ import canCapturePerformanceMetrics from './Metrics';
function diffObject(object: Record<string, unknown>, base: Record<string, unknown>): Record<string, unknown> {
function changes(obj: Record<string, unknown>, comparisonObject: Record<string, unknown>): Record<string, unknown> {
return lodashTransform(obj, (result, value, key) => {
if (isEqual(value, comparisonObject[key])) {
if (deepEqual(value, comparisonObject[key])) {
return;
}

Expand Down
4 changes: 2 additions & 2 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {findFocusedRoute} from '@react-navigation/native';
import {format} from 'date-fns';
import {Str} from 'expensify-common';
import {deepEqual} from 'fast-equals';
import lodashEscape from 'lodash/escape';
import lodashIntersection from 'lodash/intersection';
import isEmpty from 'lodash/isEmpty';
import lodashIsEqual from 'lodash/isEqual';
import isNumber from 'lodash/isNumber';
import mapValues from 'lodash/mapValues';
import lodashMaxBy from 'lodash/maxBy';
Expand Down Expand Up @@ -8042,7 +8042,7 @@ function getChatByParticipants(
const sortedParticipantsAccountIDs = participantAccountIDs.map(Number).sort();

// Only return the chat if it has all the participants
return lodashIsEqual(sortedNewParticipantList, sortedParticipantsAccountIDs);
return deepEqual(sortedNewParticipantList, sortedParticipantsAccountIDs);
});
}

Expand Down
Loading
Loading