Skip to content

Commit cfa3ffc

Browse files
authored
Merge pull request Expensify#63686 from hoangzinh/fix/63636-Improve-task-and-trip-performance
Improve task and trip related list components performance
2 parents dcce0dd + 8a83f83 commit cfa3ffc

17 files changed

Lines changed: 134 additions & 63 deletions

src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ function MoneyRequestReportActionsList({
130130
const reportID = report?.reportID;
131131
const linkedReportActionID = route?.params?.reportActionID;
132132

133+
const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false});
133134
const [parentReportAction] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${getNonEmptyStringOnyxID(report?.parentReportID)}`, {
134135
canEvict: false,
135136
canBeMissing: true,
@@ -468,6 +469,7 @@ function MoneyRequestReportActionsList({
468469

469470
return (
470471
<ReportActionsListItemRenderer
472+
allReports={allReports}
471473
reportAction={reportAction}
472474
reportActions={reportActions}
473475
parentReportAction={parentReportAction}
@@ -495,6 +497,7 @@ function MoneyRequestReportActionsList({
495497
unreadMarkerReportActionID,
496498
firstVisibleReportActionID,
497499
linkedReportActionID,
500+
allReports,
498501
],
499502
);
500503

src/components/ReportActionItem/TaskPreview.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import UserDetailsTooltip from '@components/UserDetailsTooltip';
1414
import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails';
1515
import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentUserPersonalDetails';
1616
import useLocalize from '@hooks/useLocalize';
17-
import useOnyx from '@hooks/useOnyx';
1817
import useParentReport from '@hooks/useParentReport';
1918
import useReportIsArchived from '@hooks/useReportIsArchived';
2019
import useStyleUtils from '@hooks/useStyleUtils';
@@ -30,17 +29,17 @@ import Parser from '@libs/Parser';
3029
import {isCanceledTaskReport, isOpenTaskReport, isReportManager} from '@libs/ReportUtils';
3130
import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu';
3231
import CONST from '@src/CONST';
33-
import ONYXKEYS from '@src/ONYXKEYS';
3432
import ROUTES from '@src/ROUTES';
35-
import type {ReportAction} from '@src/types/onyx';
33+
import type {Report, ReportAction} from '@src/types/onyx';
3634
import {isEmptyObject} from '@src/types/utils/EmptyObject';
3735

3836
type TaskPreviewProps = WithCurrentUserPersonalDetailsProps & {
3937
/** The ID of the associated policy */
4038
// eslint-disable-next-line react/no-unused-prop-types
4139
policyID: string | undefined;
42-
/** The ID of the associated taskReport */
43-
taskReportID: string | undefined;
40+
41+
/** The task report associated with this action, if any */
42+
taskReport: OnyxEntry<Report>;
4443

4544
/** Whether the task preview is hovered so we can modify its style */
4645
isHovered: boolean;
@@ -68,7 +67,7 @@ type TaskPreviewProps = WithCurrentUserPersonalDetailsProps & {
6867
};
6968

7069
function TaskPreview({
71-
taskReportID,
70+
taskReport,
7271
action,
7372
contextMenuAnchor,
7473
chatReportID,
@@ -83,7 +82,7 @@ function TaskPreview({
8382
const StyleUtils = useStyleUtils();
8483
const {translate} = useLocalize();
8584
const theme = useTheme();
86-
const [taskReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`, {canBeMissing: true});
85+
const taskReportID = taskReport?.reportID;
8786
const taskTitle = action?.childReportName ?? taskReport?.reportName ?? '';
8887

8988
const taskTitleWithoutImage = Parser.replace(Parser.htmlToMarkdown(taskTitle), {disabledRules: [...CONST.TASK_TITLE_DISABLED_RULES]});

src/components/ReportActionItem/TaskView.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import {ShowContextMenuContext} from '@components/ShowContextMenuContext';
1616
import Text from '@components/Text';
1717
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
1818
import useLocalize from '@hooks/useLocalize';
19-
import useParentReport from '@hooks/useParentReport';
2019
import useReportIsArchived from '@hooks/useReportIsArchived';
2120
import useStyleUtils from '@hooks/useStyleUtils';
2221
import useThemeStyles from '@hooks/useThemeStyles';
@@ -37,11 +36,14 @@ type TaskViewProps = {
3736
/** The report currently being looked at */
3837
report: OnyxEntry<Report>;
3938

39+
/** The parent report */
40+
parentReport: OnyxEntry<Report>;
41+
4042
/** The task report action */
4143
action: OnyxEntry<ReportAction>;
4244
};
4345

44-
function TaskView({report, action}: TaskViewProps) {
46+
function TaskView({report, parentReport, action}: TaskViewProps) {
4547
const styles = useThemeStyles();
4648
const StyleUtils = useStyleUtils();
4749
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
@@ -59,7 +61,6 @@ function TaskView({report, action}: TaskViewProps) {
5961

6062
const isOpen = isOpenTaskReport(report);
6163
const isCompleted = isCompletedTaskReport(report);
62-
const parentReport = useParentReport(report?.reportID);
6364
const isParentReportArchived = useReportIsArchived(parentReport?.reportID);
6465
const isTaskModifiable = canModifyTask(report, currentUserPersonalDetails.accountID, isParentReportArchived);
6566
const isTaskActionable = canActionTask(report, currentUserPersonalDetails.accountID, parentReport, isParentReportArchived);

src/components/ReportActionItem/TripRoomPreview.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {Str} from 'expensify-common';
22
import React, {useMemo} from 'react';
33
import type {ListRenderItemInfo, StyleProp, ViewStyle} from 'react-native';
44
import {FlatList, View} from 'react-native';
5+
import type {OnyxEntry} from 'react-native-onyx';
56
import Button from '@components/Button';
67
import Icon from '@components/Icon';
78
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
@@ -10,7 +11,6 @@ import {PressableWithoutFeedback} from '@components/Pressable';
1011
import {showContextMenuForReport} from '@components/ShowContextMenuContext';
1112
import Text from '@components/Text';
1213
import useLocalize from '@hooks/useLocalize';
13-
import useOnyx from '@hooks/useOnyx';
1414
import useStyleUtils from '@hooks/useStyleUtils';
1515
import useTheme from '@hooks/useTheme';
1616
import useThemeStyles from '@hooks/useThemeStyles';
@@ -27,17 +27,19 @@ import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActio
2727
import variables from '@styles/variables';
2828
import * as Expensicons from '@src/components/Icon/Expensicons';
2929
import CONST from '@src/CONST';
30-
import ONYXKEYS from '@src/ONYXKEYS';
3130
import ROUTES from '@src/ROUTES';
32-
import type {ReportAction} from '@src/types/onyx';
31+
import type {Report, ReportAction} from '@src/types/onyx';
3332
import type {Reservation} from '@src/types/onyx/Transaction';
3433

3534
type TripRoomPreviewProps = {
3635
/** All the data of the action */
3736
action: ReportAction;
3837

3938
/** The associated chatReport */
40-
chatReportID: string | undefined;
39+
chatReport: OnyxEntry<Report>;
40+
41+
/** The associated iouReport */
42+
iouReport: OnyxEntry<Report>;
4143

4244
/** Extra styles to pass to View wrapper */
4345
containerStyles?: StyleProp<ViewStyle>;
@@ -139,7 +141,8 @@ function ReservationView({reservation, onPress}: ReservationViewProps) {
139141

140142
function TripRoomPreview({
141143
action,
142-
chatReportID,
144+
chatReport,
145+
iouReport,
143146
containerStyles,
144147
contextMenuAnchor,
145148
isHovered = false,
@@ -148,8 +151,7 @@ function TripRoomPreview({
148151
}: TripRoomPreviewProps) {
149152
const styles = useThemeStyles();
150153
const {translate} = useLocalize();
151-
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`, {canBeMissing: true});
152-
const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReport?.iouReportID}`, {canBeMissing: true});
154+
const chatReportID = chatReport?.reportID;
153155
const tripTransactions = useTripTransactions(chatReportID);
154156

155157
const reservationsData: ReservationData[] = getReservationsFromTripTransactions(tripTransactions);

src/components/Search/SearchList.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import useKeyboardShortcut from '@hooks/useKeyboardShortcut';
2222
import useKeyboardState from '@hooks/useKeyboardState';
2323
import useLocalize from '@hooks/useLocalize';
2424
import useMobileSelectionMode from '@hooks/useMobileSelectionMode';
25+
import useOnyxCustomHook from '@hooks/useOnyx';
2526
import useResponsiveLayout from '@hooks/useResponsiveLayout';
2627
import useSafeAreaPaddings from '@hooks/useSafeAreaPaddings';
2728
import useThemeStyles from '@hooks/useThemeStyles';
@@ -139,6 +140,8 @@ function SearchList(
139140
canBeMissing: true,
140141
});
141142

143+
const [allReports] = useOnyxCustomHook(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false});
144+
142145
useEffect(() => {
143146
selectionRef.current = selectedItemsLength;
144147

@@ -336,6 +339,7 @@ function SearchList(
336339
queryJSONHash={queryJSONHash}
337340
policies={policies}
338341
isDisabled={isDisabled}
342+
allReports={allReports}
339343
/>
340344
);
341345
},
@@ -351,6 +355,7 @@ function SearchList(
351355
queryJSONHash,
352356
setFocusedIndex,
353357
shouldPreventDefaultFocusOnSelectRow,
358+
allReports,
354359
],
355360
);
356361

src/components/SelectionList/ChatListItem.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ function ChatListItem<TItem extends ListItem>({
2323
onLongPressRow,
2424
shouldSyncFocus,
2525
policies,
26+
allReports,
2627
}: ChatListItemProps<TItem>) {
2728
const reportActionItem = item as unknown as ReportActionListItemType;
2829
const reportID = Number(reportActionItem?.reportID ?? CONST.DEFAULT_NUMBER_ID);
@@ -70,6 +71,7 @@ function ChatListItem<TItem extends ListItem>({
7071
hoverStyle={item.isSelected && styles.activeComponentBG}
7172
>
7273
<ReportActionItem
74+
allReports={allReports}
7375
action={reportActionItem}
7476
report={report}
7577
reportActions={[]}

src/components/SelectionList/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,9 @@ type ChatListItemProps<TItem extends ListItem> = ListItemProps<TItem> & {
453453

454454
/** The policies which the user has access to */
455455
policies?: OnyxCollection<Policy>;
456+
457+
/** All the data of the report collection */
458+
allReports?: OnyxCollection<Report>;
456459
};
457460

458461
type ValidListItem =

src/pages/Debug/ReportAction/DebugReportActionCreatePage.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ import useLocalize from '@hooks/useLocalize';
1212
import useThemeStyles from '@hooks/useThemeStyles';
1313
import DateUtils from '@libs/DateUtils';
1414
import DebugUtils from '@libs/DebugUtils';
15-
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
15+
import {canUseTouchScreen} from '@libs/DeviceCapabilities';
1616
import Navigation from '@libs/Navigation/Navigation';
1717
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
1818
import type {DebugParamList} from '@libs/Navigation/types';
19-
import * as NumberUtils from '@libs/NumberUtils';
19+
import {rand64} from '@libs/NumberUtils';
2020
import ReportActionItem from '@pages/home/report/ReportActionItem';
2121
import Debug from '@userActions/Debug';
2222
import CONST from '@src/CONST';
@@ -32,7 +32,7 @@ const getInitialReportAction = (reportID: string, session: OnyxEntry<Session>, p
3232
DebugUtils.stringifyJSON({
3333
actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT,
3434
reportID,
35-
reportActionID: NumberUtils.rand64(),
35+
reportActionID: rand64(),
3636
created: DateUtils.getDBTime(),
3737
actorAccountID: session?.accountID,
3838
avatar: (session?.accountID && personalDetailsList?.[session.accountID]?.avatar) ?? '',
@@ -46,8 +46,9 @@ function DebugReportActionCreatePage({
4646
}: DebugReportActionCreatePageProps) {
4747
const {translate} = useLocalize();
4848
const styles = useThemeStyles();
49-
const [session] = useOnyx(ONYXKEYS.SESSION);
50-
const [personalDetailsList] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
49+
const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false});
50+
const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false});
51+
const [personalDetailsList] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false});
5152
const [draftReportAction, setDraftReportAction] = useState<string>(() => getInitialReportAction(reportID, session, personalDetailsList));
5253
const [error, setError] = useState<string>();
5354

@@ -78,7 +79,7 @@ function DebugReportActionCreatePage({
7879
<ScreenWrapper
7980
includeSafeAreaPaddingBottom={false}
8081
shouldEnableKeyboardAvoidingView={false}
81-
shouldEnableMinHeight={DeviceCapabilities.canUseTouchScreen()}
82+
shouldEnableMinHeight={canUseTouchScreen()}
8283
testID={DebugReportActionCreatePage.displayName}
8384
>
8485
{({safeAreaPaddingBottomStyle}) => (
@@ -105,6 +106,7 @@ function DebugReportActionCreatePage({
105106
<Text style={[styles.textLabelSupporting, styles.mb2]}>{translate('debug.preview')}</Text>
106107
{!error ? (
107108
<ReportActionItem
109+
allReports={allReports}
108110
action={JSON.parse(draftReportAction.replaceAll('\n', '')) as ReportAction}
109111
report={{reportID}}
110112
reportActions={[]}

src/pages/Debug/ReportAction/DebugReportActionPreview.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ type DebugReportActionPreviewProps = {
1515
};
1616

1717
function DebugReportActionPreview({reportAction, reportID}: DebugReportActionPreviewProps) {
18-
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
18+
const [allReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {canBeMissing: false});
19+
const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`];
1920

2021
return (
2122
<ScrollView>
2223
<ReportActionItem
24+
allReports={allReports}
2325
action={reportAction ?? ({} as ReportAction)}
2426
report={report ?? ({} as Report)}
2527
reportActions={[]}

src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
11
import React from 'react';
22
import {View} from 'react-native';
3-
import type {OnyxEntry} from 'react-native-onyx';
3+
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
44
import {useOnyx} from 'react-native-onyx';
55
import useThemeStyles from '@hooks/useThemeStyles';
6-
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
6+
import {getOriginalMessage, getReportAction, isMoneyRequestAction} from '@libs/ReportActionsUtils';
77
import ReportActionItem from '@pages/home/report/ReportActionItem';
8+
import CONST from '@src/CONST';
89
import ONYXKEYS from '@src/ONYXKEYS';
9-
import type {Transaction} from '@src/types/onyx';
10+
import type {Report, Transaction} from '@src/types/onyx';
1011

1112
type DuplicateTransactionItemProps = {
1213
transaction: OnyxEntry<Transaction>;
1314
index: number;
15+
allReports: OnyxCollection<Report>;
1416
};
1517

16-
function DuplicateTransactionItem(props: DuplicateTransactionItemProps) {
18+
function DuplicateTransactionItem({transaction, index, allReports}: DuplicateTransactionItemProps) {
1719
const styles = useThemeStyles();
18-
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${props.transaction?.reportID}`);
19-
const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.reportID}`);
20+
const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`];
21+
const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.reportID}`, {canBeMissing: false});
2022

2123
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/non-nullable-type-assertion-style
2224
const action = Object.values(reportActions ?? {})?.find((reportAction) => {
23-
const IOUTransactionID = ReportActionsUtils.isMoneyRequestAction(reportAction) ? ReportActionsUtils.getOriginalMessage(reportAction)?.IOUTransactionID : -1;
24-
return IOUTransactionID === props.transaction?.transactionID;
25+
const IOUTransactionID = isMoneyRequestAction(reportAction) ? getOriginalMessage(reportAction)?.IOUTransactionID : CONST.DEFAULT_NUMBER_ID;
26+
return IOUTransactionID === transaction?.transactionID;
2527
});
2628

2729
if (!action || !report) {
@@ -31,10 +33,11 @@ function DuplicateTransactionItem(props: DuplicateTransactionItemProps) {
3133
return (
3234
<View style={styles.pb2}>
3335
<ReportActionItem
36+
allReports={allReports}
3437
action={action}
3538
report={report}
36-
parentReportAction={ReportActionsUtils.getReportAction(report?.parentReportID ?? '', report?.parentReportActionID ?? '')}
37-
index={props.index}
39+
parentReportAction={getReportAction(report?.parentReportID, report?.parentReportActionID)}
40+
index={index}
3841
reportActions={Object.values(reportActions ?? {})}
3942
displayAsGroup={false}
4043
shouldDisplayNewMarker={false}

0 commit comments

Comments
 (0)