Fix: Patch PagerViewAdapter to call onTabSelect on initial mount for native#84002
Fix: Patch PagerViewAdapter to call onTabSelect on initial mount for native#84002
Conversation
…native On iOS native, the onTabSelect callback was never fired on initial mount because PagerViewAdapter only triggers it on user-initiated tab changes. This caused the Start Chat input to not auto-focus when opening the screen. This mirrors the existing web fix (patch 003) for PanResponderAdapter by adding a mount-time useEffect that calls onTabSelect with the initial tab index via requestAnimationFrame. Co-authored-by: Vinh Hoang <hoangzinh@users.noreply.github.com>
Split single malformed hunk into two valid hunks to eliminate blank context lines without space prefix, which caused patch-package to fail parsing the file during postinstall. Co-authored-by: Vinh Hoang <hoangzinh@users.noreply.github.com>
|
Fixed the failing checks. The patch file
I restructured the patch from one large hunk into two smaller hunks that avoid blank context lines entirely. The actual code changes are identical — same additions to |
|
The original CI failures were all caused by the patch file The second commit (
No additional code changes were needed. The remaining pending checks (iOS HybridApp build, perf-tests) are long-running jobs that are still in progress, not failing. |
|
@MelvinBot merge latest main |
…SelectOnMount Co-authored-by: Vinh Hoang <hoangzinh@users.noreply.github.com>
|
Merged latest |
|
@MelvinBot mark this issue is ready for review |
| const pagerRef = React.useRef<ViewPager>(null); | ||
| const indexRef = React.useRef<number>(index); | ||
| const navigationStateRef = React.useRef(navigationState); | ||
| + const onTabSelectRef = React.useRef(onTabSelect); |
There was a problem hiding this comment.
Yes, the useRef is needed here. The requestAnimationFrame inside the mount-only useEffect(…, []) creates an asynchronous gap — by the time the rAF callback fires (~16ms later), the onTabSelect captured in the closure could be stale if the parent re-rendered in that window. The ref ensures we always call the latest version.
That said, the ref pattern also exists for consistency: PanResponderAdapter (the web adapter) already uses onTabSelectRef as part of its original library source code (PanResponderAdapter.tsx:76), and patch 003 (the web fix) accesses onTabSelectRef.current the same way. This patch mirrors that pattern for the native adapter.
In practice the stale-closure risk on mount is very small, but the ref costs only two lines and follows the established convention in the same library.
|
I'm unable to mark this PR as ready for review due to environment permissions. You can do it yourself by clicking Ready for review at the bottom of the PR page, or by running: |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2026-03-08.at.10.51.13.android.movAndroid: mWeb ChromeScreen.Recording.2026-03-08.at.10.53.11.ac.moviOS: HybridAppScreen.Recording.2026-03-08.at.11.00.21.moviOS: mWeb SafariScreen.Recording.2026-03-08.at.10.54.17.is.movMacOS: Chrome / SafariScreen.Recording.2026-03-08.at.10.49.00.web.mov |
|
🚧 @Gonals 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/Gonals in version: 9.3.34-0 🚀
|
|
PR failed with an original issue on iOS, focus is lost when switching between Chat and Room Focus.lost.mp4 |
|
🚀 Deployed to production by https://github.com/luacmartins in version: 9.3.34-2 🚀
|
Explanation of Change
On iOS native, when opening FAB > Start Chat, the search input field was not auto-focused and the keyboard did not appear. This happened because the native
PagerViewAdapter(fromreact-native-tab-view) only fires theonTabSelectcallback when the user switches tabs — it does not fire on initial mount.The focus mechanism in
NewChatSelectorPagerelies ononTabSelectto callchatPageInputRef.current?.focus(), andNewChatPagehastextInputAutoFocus={false}. So withoutonTabSelectfiring on mount, the input was never focused.A similar fix already existed for web (patch 003 on
PanResponderAdapter). This PR adds an equivalent patch (004) for the nativePagerViewAdapterthat callsonTabSelecton initial mount via auseEffect, mirroring the web behavior.Changes:
react-native-tab-view+4.1.0+004+fix-native-onTabSelect-on-mount.patch— patchesPagerViewAdapter.tsxto callonTabSelecton mount using refs andrequestAnimationFramepatches/react-native-tab-view/details.mdwith documentation for the new patchFixed Issues
$ #83010
PROPOSAL: #83010 (comment)
Tests
Offline tests
N/A — This fix is purely a UI focus behavior change that does not depend on network state.
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
N/A — patch targets native PagerViewAdapter used on both iOS and Android. Behavior should be verified on both platforms.
Android: mWeb Chrome
N/A — this patch only affects native (PagerViewAdapter). Web uses PanResponderAdapter which already has patch 003.
iOS: Native
N/A — this is the primary platform affected. Manual testing required on device.
iOS: mWeb Safari
N/A — web is unaffected by this change.
MacOS: Chrome / Safari
N/A — web is unaffected by this change.