[No QA] fix: add span lifecycle cleanup for ManualNavigateToInboxTab#85542
Conversation
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: 5c7a0502f6
ℹ️ 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".
| useEffect(() => { | ||
| currentReportIDRef.current = currentReportID; | ||
| }, [currentReportID]); |
There was a problem hiding this comment.
Keep active report ref in sync during render
Updating currentReportIDRef in a passive useEffect introduces a stale-value window after currentReportID changes: isActiveReport() can still return the previous report until the effect runs. SidebarLinks uses this callback in showReportPage to suppress duplicate navigation on narrow layouts, so quick consecutive taps right after a report change can bypass that guard and trigger an unnecessary second navigation to the already-active report.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Thanks for the note. The project enforces a custom ESLint rule (react-hooks/refs) that disallows mutating refs during render, so useEffect is the required pattern here. The stale-value window is one render cycle at most, and isActiveReport is only called in response to user interaction (tap on a report row), which cannot physically happen within that window.
|
@rojiphil can you review please |
|
@JS00001 Reviewing now |
Reviewer Checklist
Screenshots/VideosAndroid: HybridApp85542-android-hybrid-002.mp4Android: mWeb Chrome85542-mweb-chrome-001.mp4iOS: HybridAppRan into build issues locally but I think it should be fine as android hybrid version is tested. iOS: mWeb Safari85542-mweb-safari-001.mp4MacOS: Chrome / Safari85542-web-chrome-001.mp4 |
|
🚧 @JS00001 has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by https://github.com/JS00001 in version: 9.3.41-0 🚀
Bundle Size Analysis (Sentry): |
|
🚀 Deployed to production by https://github.com/cristipaval in version: 9.3.41-4 🚀
|
Explanation of Change
ManualNavigateToInboxTabspans were leaking inflated durations (7-10% of all spans) due to two missing cleanup paths inSidebarLinksData:useFocusEffecthad an early return whenhasHadFirstLayoutwas false, so it never registered a cleanup function. If the user navigated away before the first layout completed (rapid tab switching, navigation interruption), the orphaned span was never canceled.Fix:
useFocusEffectcondition so the blur cleanup (cancelSpan) is always returned, regardless of layout state. On focus,endSpanonly runs if the first layout already happened (re-visit from freeze).useEffectunmount cleanup with a span identity guard: cancels the span only if layout never completed AND the active span matches the one captured at mount time. This avoids accidentally canceling a newer span started by a subsequent tab click. Pattern mirrorsSPAN_NAVIGATE_TO_REPORTSinSearch/index.tsx.currentReportIDRef.currentassignment intouseEffectto resolvereact-hooks/refslint warning that was blocking commits to this file.Fixed Issues
$ #77175
PROPOSAL:
Tests
Offline tests
N/A - telemetry span cleanup only, no network behavior changes.
QA Steps
Same as Tests above.
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: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari