Defer API.write during Search screen transition to reduce perceived latency#85629
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c5dca7ff1f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@ShridharGoel 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] |
Codecov Report❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 131594a048
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2026-03-20.at.12.47.42.AM.movAndroid: mWeb ChromeiOS: HybridAppiOS: mWeb SafariMacOS: Chrome / SafariScreen.Recording.2026-03-20.at.1.28.43.PM.mov |
|
It shows the empty state while the new expense hasn't loaded. Screen.Recording.2026-03-20.at.1.33.56.PM.mov |
|
@ShridharGoel can you prioritize this review when you're online please? |
|
NAB: The list doesn't get updated unless we refresh or switch between menu items after creating expense offline and then going online. But seems like the same thing happens on staging as well. Also, the new expense wasn't showing optimistically when created offline while being on the search page (also happening on staging). Screen.Recording.2026-03-24.at.10.15.49.AM.mov |
|
Yeah, the above happening on staging + I've pretty much not touched submitting expense while being on the Search page at all (only when submitting outside Inbox & Search page) |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e56416a901
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 366b72356a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const safetyTimeoutId = setTimeout(() => { | ||
| Log.warn(`[DeferredLayoutWrite] Safety timeout (${safetyTimeoutMs}ms) fired for key "${key}" - the target component likely never laid out`); | ||
| flushDeferredWrite(key); | ||
| }, safetyTimeoutMs); |
There was a problem hiding this comment.
Persist deferred writes across app restarts
registerDeferredWrite() stores the pending API.write callback only in memory and depends on a JS setTimeout/layout flush to execute it. For the newly deferred expense submission paths, if the app is background-killed or restarted before Search lays out (or before the 5s timeout fires), the callback is lost and the expense request is never queued or sent. Before this change, those flows called API.write immediately, so this introduces a real data-loss window for submit actions.
Useful? React with 👍 / 👎.
|
@JakubKorytko is still addressing this comment #85629 (comment) |
Explanation of Change
Reduces perceived latency when navigating to the Search screen after expense creation.
API.write()calls (which trigger expensive Onyx optimistic updates) are now deferred until the Search content actually lays out, preventing JS thread blocking during the skeleton -> content transition.This benefits all platforms (mobile native, mWeb, and desktop web) though the mobile is the most noticeable.
Also optimizes
SearchContextto avoid unnecessary re-renders by extracting primitives from navigation state and memoizing callbacks/values.Removes the
DeferredSearchwrapper in favor of the simpler direct approach.2408 ms -> 893 ms (span average) native mobile improvement.
Fixed Issues
$ #83634
$ #83342
PROPOSAL: N/A
Tests
SearchContextoptimizations)Offline tests
QA Steps
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
android.mov
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
web.mov