Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions patches/react-native-tab-view/details.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
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,3 +57,5 @@ export function PagerViewAdapter<T extends Route>({
const pagerRef = React.useRef<ViewPager>(null);
const indexRef = React.useRef<number>(index);
const navigationStateRef = React.useRef(navigationState);
+ const onTabSelectRef = React.useRef(onTabSelect);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MelvinBot Do we need to use useRef here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

+ const hasCalledInitialTabSelectRef = React.useRef(false);
@@ -64,3 +66,15 @@ export function PagerViewAdapter<T extends Route>({
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});
+ });
+ }, []);
Loading