Perf: Defer Search/Reports list mount via NavigationDeferredMount#91848
Open
dariusz-biela wants to merge 1 commit into
Open
Conversation
Introduce SearchWithNavigationDeferredMount that wraps Search in NavigationDeferredMount with a SearchRowSkeleton placeholder. The placeholder ends the ManualNavigateToReports span with is_warm=true at first layout, so warm first mount measures to skeleton visible while the heavy list hydrates after the navigation transition completes. Refocus through react-freeze still ends the span via Search's existing useFocusEffect, so cached navigations keep measuring to list visible without showing a skeleton. Used by SearchPageWide and SearchPageNarrow (non-static branch) in place of the previous inline render so the spread-props wrapper handles narrow vs wide container styling internally via useResponsiveLayout.
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
|
@marufsharifi Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
|
@mananjadhav @luacmartins One of you needs to copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation of Change
Warm start of the Reports/Search page (first render in a session, data already cached) takes ~550ms (Mac M4 Pro) because we wait for the full list to render before showing anything to the user. This PR applies
NavigationDeferredMountto that path so the warm start behaves like a cold start visually:SearchPage, aSearchRowSkeletonplaceholder paints immediately and endsManualNavigateToReportswithis_warm: true.Searchsubtree mounts insidestartTransitionafter the navigation transition completes, so the list does not compete with the navigation animation frame budget.Search, do not show the skeleton, and end the span via the existinguseFocusEffect— that path still measures to list visible.Implementation:
src/components/Search/SearchWithNavigationDeferredMount.tsx. AcceptsComponentProps<typeof Search>, picks the placeholder container style fromuseResponsiveLayout()+props.hasFilterBars, and spreads props toSearch.SearchPageWideandSearchPageNarrow(non-static branch) renderSearchWithNavigationDeferredMountinstead ofSearchdirectly. The static-rendering branch inSearchPageNarrow(post-submit overlay path) is left untouched.Results:
Warm full - this is the time it takes for the first warm render to display the full list, rather than just the skeleton.
Fixed Issues
$ #91731
PROPOSAL:
Tests
Offline tests
Same as Tests.
QA Steps
Same as Tests.
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Screen.Recording.2026-05-27.at.16.46.29.mp4
iOS: Native
Screen.Recording.2026-05-27.at.16.42.14.mp4
MacOS: Chrome / Safari
Screen.Recording.2026-05-27.at.16.36.52.mp4