@@ -512,6 +512,21 @@ function MoneyRequestReportPreviewContent({
512512 // undefined makes arrow buttons react on currentIndex changes when scrolling manually
513513 const [ optimisticIndex , setOptimisticIndex ] = useState < number | undefined > ( undefined ) ;
514514 const carouselRef = useRef < FlashListRef < Transaction > | null > ( null ) ;
515+ const prevTransactionCountForScroll = useRef ( carouselTransactions . length ) ;
516+ const [ carouselKey , setCarouselKey ] = useState ( 0 ) ;
517+
518+ // Reset carousel when transitioning from empty to non-empty data.
519+ // scrollToOffset doesn't clear RecyclerListView's internal layout cache on iOS mobile web,
520+ // so we force a full re-mount via key to prevent new items from rendering off-screen.
521+ useEffect ( ( ) => {
522+ if ( carouselTransactions . length > 0 && prevTransactionCountForScroll . current === 0 ) {
523+ setCurrentIndex ( 0 ) ;
524+ setOptimisticIndex ( undefined ) ;
525+ setCarouselKey ( ( prev ) => prev + 1 ) ;
526+ }
527+ prevTransactionCountForScroll . current = carouselTransactions . length ;
528+ } , [ carouselTransactions . length ] ) ;
529+
515530 const visibleItemsOnEndCount = useMemo ( ( ) => {
516531 const lastItemWidth = transactions . length > MAX_PREVIEWS_NUMBER ? footerWidth : reportPreviewStyles . transactionPreviewCarouselStyle . width ;
517532 const lastItemWithGap = lastItemWidth + styles . gap2 . gap ;
@@ -988,6 +1003,7 @@ function MoneyRequestReportPreviewContent({
9881003 ) : (
9891004 < View style = { [ styles . flex1 , styles . flexColumn , styles . overflowVisible , styles . minHeight42 ] } >
9901005 < FlashList
1006+ key = { carouselKey }
9911007 snapToAlignment = "start"
9921008 decelerationRate = "fast"
9931009 snapToOffsets = { snapOffsets }
0 commit comments