From ad27d73fe3cbeffd523dd575506ba0679468da11 Mon Sep 17 00:00:00 2001 From: "Vinh Hoang (via MelvinBot)" Date: Tue, 3 Mar 2026 08:19:06 +0000 Subject: [PATCH 1/2] Fix: Patch PagerViewAdapter to call onTabSelect on initial mount for 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 --- patches/react-native-tab-view/details.md | 11 +++++++ ...+004+fix-native-onTabSelect-on-mount.patch | 33 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 patches/react-native-tab-view/react-native-tab-view+4.1.0+004+fix-native-onTabSelect-on-mount.patch diff --git a/patches/react-native-tab-view/details.md b/patches/react-native-tab-view/details.md index 0ed399a7e1911..1e87cab148c3f 100644 --- a/patches/react-native-tab-view/details.md +++ b/patches/react-native-tab-view/details.md @@ -34,3 +34,14 @@ - Upstream PR/issue: 🛑 (must merge https://github.com/react-navigation/react-navigation/pull/12627 first) - E/App issue: https://github.com/Expensify/App/issues/71913#issuecomment-3584103273 - PR Introducing Patch: [#76586](https://github.com/Expensify/App/pull/76586) + +### [react-native-tab-view+4.1.0+004+fix-native-onTabSelect-on-mount.patch](react-native-tab-view+4.1.0+004+fix-native-onTabSelect-on-mount.patch) + +- Reason: + ``` + This patch fixes an issue on iOS native where the `onTabSelect` callback was not being called on initial mount + in the PagerViewAdapter. This mirrors the web fix from patch 003 (PanResponderAdapter) and ensures the input + field is auto-focused when opening the Start Chat screen on iOS. + ``` +- Upstream PR/issue: 🛑 (must merge https://github.com/react-navigation/react-navigation/pull/12627 first) +- E/App issue: https://github.com/Expensify/App/issues/83010 diff --git a/patches/react-native-tab-view/react-native-tab-view+4.1.0+004+fix-native-onTabSelect-on-mount.patch b/patches/react-native-tab-view/react-native-tab-view+4.1.0+004+fix-native-onTabSelect-on-mount.patch new file mode 100644 index 0000000000000..99333bafb9acc --- /dev/null +++ b/patches/react-native-tab-view/react-native-tab-view+4.1.0+004+fix-native-onTabSelect-on-mount.patch @@ -0,0 +1,33 @@ +diff --git a/node_modules/react-native-tab-view/src/PagerViewAdapter.tsx b/node_modules/react-native-tab-view/src/PagerViewAdapter.tsx +index d66b0cb..a1b2c3d 100644 +--- a/node_modules/react-native-tab-view/src/PagerViewAdapter.tsx ++++ b/node_modules/react-native-tab-view/src/PagerViewAdapter.tsx +@@ -57,13 +57,25 @@ export function PagerViewAdapter({ + const pagerRef = React.useRef(null); + const indexRef = React.useRef(index); + const navigationStateRef = React.useRef(navigationState); ++ const onTabSelectRef = React.useRef(onTabSelect); ++ const hasCalledInitialTabSelectRef = React.useRef(false); + + const position = useAnimatedValue(index); + const offset = useAnimatedValue(0); + + React.useEffect(() => { + navigationStateRef.current = navigationState; ++ onTabSelectRef.current = onTabSelect; + }); + ++ React.useEffect(() => { ++ if (hasCalledInitialTabSelectRef.current) { ++ return; ++ } ++ hasCalledInitialTabSelectRef.current = true; ++ // Call onTabSelect on initial mount (parity with web PanResponderAdapter patch) ++ requestAnimationFrame(() => { ++ onTabSelectRef.current?.({index: navigationStateRef.current.index}); ++ }); ++ }, []); ++ + const jumpTo = useLatestCallback((key: string) => { + const index = navigationStateRef.current.routes.findIndex( + (route: { key: string }) => route.key === key From d92a8d17c6edb4a0e3ea83b712f753cba3e58576 Mon Sep 17 00:00:00 2001 From: "Vinh Hoang (via MelvinBot)" Date: Tue, 3 Mar 2026 08:38:06 +0000 Subject: [PATCH 2/2] Fix: Reformat patch file to fix patch-package parse error 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 --- ...+4.1.0+004+fix-native-onTabSelect-on-mount.patch | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/patches/react-native-tab-view/react-native-tab-view+4.1.0+004+fix-native-onTabSelect-on-mount.patch b/patches/react-native-tab-view/react-native-tab-view+4.1.0+004+fix-native-onTabSelect-on-mount.patch index 99333bafb9acc..1c926949ef447 100644 --- a/patches/react-native-tab-view/react-native-tab-view+4.1.0+004+fix-native-onTabSelect-on-mount.patch +++ b/patches/react-native-tab-view/react-native-tab-view+4.1.0+004+fix-native-onTabSelect-on-mount.patch @@ -2,21 +2,18 @@ diff --git a/node_modules/react-native-tab-view/src/PagerViewAdapter.tsx b/node_ index d66b0cb..a1b2c3d 100644 --- a/node_modules/react-native-tab-view/src/PagerViewAdapter.tsx +++ b/node_modules/react-native-tab-view/src/PagerViewAdapter.tsx -@@ -57,13 +57,25 @@ export function PagerViewAdapter({ +@@ -57,3 +57,5 @@ export function PagerViewAdapter({ const pagerRef = React.useRef(null); const indexRef = React.useRef(index); const navigationStateRef = React.useRef(navigationState); + const onTabSelectRef = React.useRef(onTabSelect); + const hasCalledInitialTabSelectRef = React.useRef(false); - - const position = useAnimatedValue(index); - const offset = useAnimatedValue(0); - +@@ -64,3 +66,15 @@ export function PagerViewAdapter({ React.useEffect(() => { navigationStateRef.current = navigationState; + onTabSelectRef.current = onTabSelect; }); - ++ + React.useEffect(() => { + if (hasCalledInitialTabSelectRef.current) { + return; @@ -27,7 +24,3 @@ index d66b0cb..a1b2c3d 100644 + onTabSelectRef.current?.({index: navigationStateRef.current.index}); + }); + }, []); -+ - const jumpTo = useLatestCallback((key: string) => { - const index = navigationStateRef.current.routes.findIndex( - (route: { key: string }) => route.key === key