Freeze non top screens to prevent extra-rerenders 2#85443
Conversation
|
|
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
|
FYI, there is a bug with newly created account for gmail user - I can't pass through the onboarding modal. This happens on main too, so it's not related to current pr: main-bug-onboarding.mp4 |
|
@MelvinBot please post summary of new changes which fix regressions from v1 PR. |
.../PlatformStackNavigation/createPlatformStackNavigatorComponent/ScreenFreezeWrapper/index.tsx
Show resolved
Hide resolved
.../PlatformStackNavigation/createPlatformStackNavigatorComponent/ScreenFreezeWrapper/index.tsx
Show resolved
Hide resolved
Summary of New Changes Fixing v1 RegressionsThis PR re-applies the original v1 PR (#82764) and adds three fix commits on top to address the five regressions that caused the revert. Here's what each fix does: 1. Fix for #85184 — Web: App freezes when clicking "Go to Expensify Cards" buttonCommit: The original Fix: Added an 2. Fix for #85170, #85185, #85250 — iOS: Gray-out on swipe-back, Copilot unresponsive, Downgrade freezeCommit: All three iOS issues shared the same root cause: on Fabric, the Fix: Introduced a 3. Fix for #85149 — Web: ENTER on Merchant opens Schedule Call after visiting #adminsCommit: When a screen was frozen, its keyboard shortcuts were supposed to unsubscribe via cleanup effects. But the freeze happened before cleanup could run, leaving stale shortcuts from a previously visited screen (e.g., #admins' "Schedule Call" shortcut) still active. Pressing Enter would trigger that stale shortcut instead of the expected action. Fix: Introduced a freeze defer mechanism:
TL;DR: The three fix commits address: (1) modal-awareness in freeze logic, (2) a longer delay for iOS native animations before freezing, and (3) a defer mechanism so keyboard shortcut cleanup runs before screens are frozen. |
Code Review: Freeze non-top screens v2Overall this is a well-structured approach to preventing unnecessary re-renders. The 1.
|
| # | Issue | Severity | Type |
|---|---|---|---|
| 1 | contextValue not memoized — causes re-renders of all keyboard shortcut consumers in split screens |
Medium | Performance |
| 2 | rAF timing in submitAndClose may fire before native DelayedFreeze unfreezes target screen |
Medium | Correctness |
| 3 | wrappedDescriptors not memoized |
Low | Performance |
| 4 | DelayedFreeze delays unfreezing by 400ms — should unfreeze immediately |
Medium | Design |
| 5 | Minor: magic number, missing dep, missing comment | Low | Code quality |
Items 1 and 4 seem most actionable. The rest are worth discussing but may be acceptable tradeoffs.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e5450de216
ℹ️ 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 id = setTimeout(() => { | ||
| + rafID = requestAnimationFrame(() => setFreezeState(freeze)); | ||
| + }, FREEZE_DELAY_MS); |
There was a problem hiding this comment.
Unfreeze screens immediately when focus returns
This effect now waits FREEZE_DELAY_MS for all freeze transitions, not just when entering the frozen state. When a route becomes focused again (freeze flips true -> false), setFreezeState(false) is delayed by ~400ms, so the newly focused screen can remain suspended and miss immediate UI updates/taps after back/pop navigation. The delay should only apply when freeze is true, while unfreezing should happen immediately.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
In DelayedFreeze if freeze is false it always applied right away, https://github.com/software-mansion/react-native-screens/blob/63b3baab65a1fd36da04ae426f98ad460217e1e0/src/components/helpers/DelayedFreeze.tsx#L24
return <Freeze freeze={freeze ? freezeState : false}>{children}</Freeze>;
|
Melvin's comments don't look accurate to me, as it thinks that unfreezing is delayed too, but it's not, as I've mentioned here #85443 (comment). |
|
Currently blocked hybrid iOS testing https://expensify.slack.com/archives/C05LX9D6E07/p1773753991898119 |
|
No product review needed |
situchan
left a comment
There was a problem hiding this comment.
@MelvinBot review
Find any possible regressions. Especially from useKeyboardShortcut migration
🔍 Regression Review:
|
| Finding | Risk | Action Suggested |
|---|---|---|
captureOnInputs mismatch in CarouselActions |
Medium | Add {captureOnInputs: false} or confirm new default is intended |
onConfirm RAF deferral timing on iOS |
Medium | Verify on iOS that composerRef is available after one frame |
BaseGenericPressable migration |
None | Correct |
useCopySelectionHelper migration |
None | Correct |
modifiers?.join() change |
None | Fixes latent bug |
| ScreenFreezeContext native no-op | None | Intentional design |
setNavigationActionToMicrotaskQueue removal |
Low | Monitor for navigation race conditions |
| Unmemoized contextValue | Negligible | Optional optimization |
|
Bug: Not able to move cursor in password input of protected pdf Screen.Recording.2026-04-02.at.7.44.03.PM.mov |
|
@situchan I think my latest commit should fix it |
|
🚧 @Julesssss 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! 🧪🧪
|
...bs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent/index.native.tsx
Show resolved
Hide resolved
...rmStackNavigation/createPlatformStackNavigatorComponent/ScreenFreezeWrapper/index.native.tsx
Show resolved
Hide resolved
src/pages/workspace/members/WorkspaceInviteMessageComponent.tsx
Outdated
Show resolved
Hide resolved
Won't this reintroduce iOS issue anymore? |
Initally, I've added this update to fix this reported issue. Test steps:
But with latest updates I wasn't able to reproduce it anymore. |
|
🚧 @Julesssss 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! 🧪🧪
|
|
@Julesssss @situchan kind bump here! |
|
|
|
🚧 @Julesssss 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/Julesssss in version: 9.3.54-0 🚀
Bundle Size Analysis (Sentry): |
|
No help site changes required. This PR is a purely internal performance optimization that freezes non-top screens in the navigation stack to prevent unnecessary re-renders. It introduces a No user-facing features, settings, labels, buttons, or workflows were added, changed, or removed — so no updates to |
Explanation of Change
Freezes non-top screens in the navigation stack to prevent unnecessary re-renders, using a ScreenFreezeWrapper.
Previous PR #82764 was reverted #85198 with the next blockers:
$ #85184
$ #85185
$ #85149
$ #85170
$ #85250
Fixed Issues
$ #33725
PROPOSAL: https://expensify.slack.com/archives/C05LX9D6E07/p1771428903641059
$ #9402
Tests
#85184 — Web: App freezes when clicking "Go to Expensify Cards" button
Preconditions: Have a workspace with Expensify cards enabled. At least one Expensify card is assigned with the limit type set to Smart limit.
#85185 — iOS: App becomes unresponsive when changing Copilot access
Preconditions: Account has a copilot set.
#85149 — Web: ENTER on Merchant opens Schedule Call after visiting #admins
Additional keboard shortcuts to check:
#85170 — iOS: Workspace settings gray out briefly after swiping back
#85250 — iOS: App freezes on downgrade workspace page
Offline tests
Same, as in the Tests section
QA Steps
// TODO: These must be filled out, or the issue title must include "[No QA]."
Same, as in the Tests section
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.mp4
Android: mWeb Chrome
android_web.mp4
iOS: Native
ios.mov
ios-85250.mov
ios-85170.mov
ios-85185.mp4
iOS: mWeb Safari
ios_web.mov
MacOS: Chrome / Safari
web.mp4
web-85149.mp4
web-85184.mp4