From 87c5d6d939c631a155b34105ad05695c6ccee05a Mon Sep 17 00:00:00 2001
From: jakubstec <jakub.stec@swmansion.com>
Date: Mon, 18 May 2026 14:42:22 +0200
Subject: [PATCH 1/2] fix: remove skeleton loader in the report after creating
 expense and update comments

---
 .../MoneyRequestReportActionsList.tsx                     | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
index 7a607051dfe4..26b6c43a7f50 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
@@ -658,9 +658,13 @@ function MoneyRequestReportActionsList({onLayout}: MoneyRequestReportListProps)
     // This is intentional: we only check on the initial render after the RHP dismisses.
     // Once the deferred write flushes and createTransaction runs, Onyx updates make
     // transactions non-empty, which drives the transition away from the skeleton.
+    // isEmpty(reportActions) prevents the skeleton from showing for already-initialised reports
+    // (those with a CREATED action): the CREATED action is always present but filtered from
+    // visibleReportActions, so without this guard isReportEmpty would be true even for reports
+    // that already have server-side content.
     // Scoping to `report.reportID` ensures an unrelated submit flow's pending dismiss doesn't keep
     // *this* report stuck on the skeleton.
-    const isAwaitingDeferredTransaction = isReportEmpty && hasDeferredWriteForReport(CONST.DEFERRED_LAYOUT_WRITE_KEYS.DISMISS_MODAL, report?.reportID);
+    const isAwaitingDeferredTransaction = isReportEmpty && isEmpty(reportActions) && hasDeferredWriteForReport(CONST.DEFERRED_LAYOUT_WRITE_KEYS.DISMISS_MODAL, report?.reportID);
     const showEmptyState = isReportEmpty && !isAwaitingDeferredTransaction;
 
     if (!report) {
@@ -684,7 +688,7 @@ function MoneyRequestReportActionsList({onLayout}: MoneyRequestReportListProps)
                     onClick={scrollToBottomAndMarkReportAsRead}
                 />
                 {/* Exactly one of these three branches is active at a time:
-                    1. isAwaitingDeferredTransaction — skeleton while dismiss-first creates the transaction
+                    1. isAwaitingDeferredTransaction — skeleton while dismiss-first creates the first transaction on a report with no reportActions yet
                     2. showEmptyState — genuinely empty report
                     3. !isReportEmpty — report has data, render the FlatList */}
                 {isAwaitingDeferredTransaction && <ReportActionsListLoadingSkeleton reasonAttributes={skeletonReasonAttributes} />}

From a896d3121fc0f338a34fd985cac23749cd6a2e07 Mon Sep 17 00:00:00 2001
From: jakubstec <jakub.stec@swmansion.com>
Date: Mon, 18 May 2026 14:48:56 +0200
Subject: [PATCH 2/2] fix: refactor, remove dead code

---
 .../MoneyRequestReportActionsList.tsx         | 22 ++++---------------
 1 file changed, 4 insertions(+), 18 deletions(-)

diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
index 26b6c43a7f50..336674915180 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
@@ -26,7 +26,6 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import useWindowDimensions from '@hooks/useWindowDimensions';
 import {isConsecutiveChronosAutomaticTimerAction} from '@libs/ChronosUtils';
 import DateUtils from '@libs/DateUtils';
-import {hasDeferredWriteForReport} from '@libs/deferredLayoutWrite';
 import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
 import {getAllNonDeletedTransactions, isActionVisibleOnMoneyRequestReport} from '@libs/MoneyRequestReportUtils';
 import Navigation from '@libs/Navigation/Navigation';
@@ -654,18 +653,7 @@ function MoneyRequestReportActionsList({onLayout}: MoneyRequestReportListProps)
     }, [styles.chatItem.paddingBottom, styles.chatItem.paddingTop, windowHeight, linkedReportActionID]);
 
     const isReportEmpty = isEmpty(visibleReportActions) && isEmpty(transactions) && !showReportActionsLoadingState;
-    // hasDeferredWriteForReport is non-reactive (reads a module-level Map, not tracked by React).
-    // This is intentional: we only check on the initial render after the RHP dismisses.
-    // Once the deferred write flushes and createTransaction runs, Onyx updates make
-    // transactions non-empty, which drives the transition away from the skeleton.
-    // isEmpty(reportActions) prevents the skeleton from showing for already-initialised reports
-    // (those with a CREATED action): the CREATED action is always present but filtered from
-    // visibleReportActions, so without this guard isReportEmpty would be true even for reports
-    // that already have server-side content.
-    // Scoping to `report.reportID` ensures an unrelated submit flow's pending dismiss doesn't keep
-    // *this* report stuck on the skeleton.
-    const isAwaitingDeferredTransaction = isReportEmpty && isEmpty(reportActions) && hasDeferredWriteForReport(CONST.DEFERRED_LAYOUT_WRITE_KEYS.DISMISS_MODAL, report?.reportID);
-    const showEmptyState = isReportEmpty && !isAwaitingDeferredTransaction;
+    const showEmptyState = isReportEmpty;
 
     if (!report) {
         return null;
@@ -687,11 +675,9 @@ function MoneyRequestReportActionsList({onLayout}: MoneyRequestReportListProps)
                     isActive={isFloatingMessageCounterVisible}
                     onClick={scrollToBottomAndMarkReportAsRead}
                 />
-                {/* Exactly one of these three branches is active at a time:
-                    1. isAwaitingDeferredTransaction — skeleton while dismiss-first creates the first transaction on a report with no reportActions yet
-                    2. showEmptyState — genuinely empty report
-                    3. !isReportEmpty — report has data, render the FlatList */}
-                {isAwaitingDeferredTransaction && <ReportActionsListLoadingSkeleton reasonAttributes={skeletonReasonAttributes} />}
+                {/* Exactly one of these two branches is active at a time:
+                    1. showEmptyState — genuinely empty report
+                    2. !isReportEmpty — report has data, render the FlatList */}
                 {showEmptyState && (
                     <ScrollView contentContainerStyle={styles.flexGrow1}>
                         <MoneyRequestViewReportFields
