@@ -270,7 +270,8 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
270270 const [ currentUserEmail ] = useOnyx ( ONYXKEYS . SESSION , { selector : ( value ) => value ?. email , canBeMissing : false } ) ;
271271 const [ isLoadingApp ] = useOnyx ( ONYXKEYS . IS_LOADING_APP , { canBeMissing : true } ) ;
272272 const { reportActions : unfilteredReportActions , linkedAction, sortedAllReportActions, hasNewerActions, hasOlderActions} = usePaginatedReportActions ( reportID , reportActionIDFromRoute ) ;
273- const reportActions = getFilteredReportActionsForReportView ( unfilteredReportActions ) ;
273+ // wrapping in useMemo because this is array operation and can cause performance issues
274+ const reportActions = useMemo ( ( ) => getFilteredReportActionsForReportView ( unfilteredReportActions ) , [ unfilteredReportActions ] ) ;
274275 const [ childReport ] = useOnyx ( `${ ONYXKEYS . COLLECTION . REPORT } ${ linkedAction ?. childReportID } ` , { canBeMissing : true } ) ;
275276
276277 const [ isBannerVisible , setIsBannerVisible ] = useState ( true ) ;
@@ -300,14 +301,19 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
300301 const { transactions : allReportTransactions } = useTransactionsAndViolationsForReport ( reportIDFromRoute ) ;
301302
302303 const reportTransactions = useMemo ( ( ) => getAllNonDeletedTransactions ( allReportTransactions , reportActions ) , [ allReportTransactions , reportActions ] ) ;
303- const visibleTransactions = reportTransactions ?. filter ( ( transaction ) => isOffline || transaction . pendingAction !== CONST . RED_BRICK_ROAD_PENDING_ACTION . DELETE ) ;
304- const reportTransactionIDs = visibleTransactions ?. map ( ( transaction ) => transaction . transactionID ) ;
304+ // wrapping in useMemo because this is array operation and can cause performance issues
305+ const visibleTransactions = useMemo (
306+ ( ) => reportTransactions ?. filter ( ( transaction ) => isOffline || transaction . pendingAction !== CONST . RED_BRICK_ROAD_PENDING_ACTION . DELETE ) ,
307+ [ reportTransactions , isOffline ] ,
308+ ) ;
309+ const reportTransactionIDs = useMemo ( ( ) => visibleTransactions ?. map ( ( transaction ) => transaction . transactionID ) , [ visibleTransactions ] ) ;
305310 const transactionThreadReportID = getOneTransactionThreadReportID ( report , chatReport , reportActions ?? [ ] , isOffline , reportTransactionIDs ) ;
306311 const [ transactionThreadReportActions = getEmptyObject < OnyxTypes . ReportActions > ( ) ] = useOnyx ( `${ ONYXKEYS . COLLECTION . REPORT_ACTIONS } ${ transactionThreadReportID } ` , {
307312 canBeMissing : true ,
308313 } ) ;
309314 const combinedReportActions = getCombinedReportActions ( reportActions , transactionThreadReportID ?? null , Object . values ( transactionThreadReportActions ) ) ;
310315 const lastReportAction = [ ...combinedReportActions , parentReportAction ] . find ( ( action ) => canEditReportAction ( action ) && ! isMoneyRequestAction ( action ) ) ;
316+ // wrapping in useMemo to stabilize children re-rendering
311317 const policy = policies ?. [ `${ ONYXKEYS . COLLECTION . POLICY } ${ report ?. policyID } ` ] ;
312318 const isTopMostReportId = currentReportIDValue ?. currentReportID === reportIDFromRoute ;
313319 const didSubscribeToReportLeavingEvents = useRef ( false ) ;
@@ -756,6 +762,12 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
756762 const onComposerFocus = useCallback ( ( ) => setIsComposerFocus ( true ) , [ ] ) ;
757763 const onComposerBlur = useCallback ( ( ) => setIsComposerFocus ( false ) , [ ] ) ;
758764
765+ // wrapping into useMemo to stabilize children re-renders as reportMetadata is changed frequently
766+ const showReportActionsLoadingState = useMemo (
767+ ( ) => reportMetadata ?. isLoadingInitialReportActions && ! reportMetadata ?. hasOnceLoadedReportActions ,
768+ [ reportMetadata ?. isLoadingInitialReportActions , reportMetadata ?. hasOnceLoadedReportActions ] ,
769+ ) ;
770+
759771 // Define here because reportActions are recalculated before mount, allowing data to display faster than useEffect can trigger.
760772 // If we have cached reportActions, they will be shown immediately.
761773 // We aim to display a loader first, then fetch relevant reportActions, and finally show them.
@@ -833,7 +845,7 @@ function ReportScreen({route, navigation}: ReportScreenProps) {
833845 newTransactions = { newTransactions }
834846 hasOlderActions = { hasOlderActions }
835847 hasNewerActions = { hasNewerActions }
836- showReportActionsLoadingState = { reportMetadata ?. isLoadingInitialReportActions && ! reportMetadata ?. hasOnceLoadedReportActions }
848+ showReportActionsLoadingState = { showReportActionsLoadingState }
837849 />
838850 ) : null }
839851 { isCurrentReportLoadedFromOnyx ? (
0 commit comments