-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Description
Current behavior
When using the native bottom tab navigator (createNativeBottomTabNavigator from @react-navigation/bottom-tabs/unstable) on Android with React Navigation 7.x, three critical bugs make the navigator unusable in production:
Issue 1: Blank/White Screen After Returning from Outer Stack Navigation (Old Architecture)
What Happens:
When navigating from any bottom tab to a screen outside the tab navigator (e.g., a modal, settings screen, or any screen in the root stack) and then returning via back button or navigation.goBack(), all tab content disappears. The bottom tab bar remains visible, but every tab shows a completely blank/white screen. The app appears frozen from the user's perspective.
Steps to Reproduce:
- Set up a native bottom tab navigator with nested stack navigators
- Create a root stack that contains the bottom tab navigator and an outer screen
- Navigate from any tab to the outer screen using
navigation.navigate('OuterScreen') - Press the hardware back button or call
navigation.goBack() - Result: All tabs show blank screens
Root Cause:
In TabsHost.kt, the onAttachedToWindow() method only updates the container when IS_NEW_ARCHITECTURE_ENABLED is true. When the parent ScreenFragment is recreated during outer stack navigation, the old architecture doesn't restore tab fragments properly.
Issue 2: Tab Content Disappears When Switching Between Tabs After Deep Navigation
What Happens:
After navigating 2-3 levels deep into a tab's stack (e.g., ScreenA → ScreenA1 → ScreenA2) and then switching to another tab via the tab bar, when you return to the original tab, the screen content is blank. The header may still render, but the screen body is completely empty.
Steps to Reproduce:
- Create bottom tabs with nested stacks containing multiple screens
- Navigate deep into one tab:
navigation.navigate('ScreenA1')→navigation.navigate('ScreenA2') - Tap another tab in the tab bar to switch tabs
- Tap back to the original tab
- Result: Screen content is missing, only header visible (if any)
Root Cause:
In TabsHost.kt, the nativeFocusChange() method has an early return when newFocusedTab === oldFocusedTab. However, after parent fragment recreation, the fragment might be the same instance but its view is not properly attached to contentView. The early return prevents re-attachment.
Issue 3: ScrollView Content Hidden Under Native Tab Bar (No Automatic Padding)
What Happens:
Unlike React Navigation's JavaScript bottom tabs, the native bottom tab bar doesn't provide automatic bottom padding. When scrolling to the bottom of a ScrollView, FlatList, or any scrollable content, the last ~56dp (Material Design bottom navigation height) is hidden behind the tab bar and cannot be reached by the user.
Steps to Reproduce:
- Create a screen with long scrollable content inside a bottom tab
- Scroll to the very bottom
- Result: Last portion of content is unreachable, hidden under tab bar
Root Cause:
- React Navigation's JavaScript tabs use
BottomTabBarHeightContextwith theuseBottomTabBarHeight()hook - Native bottom tab bar doesn't emit height events to JavaScript
- The context remains
undefined, so automatic padding isn't applied to scrollable components
Testing Details:
- Reproduction rate: 100% (consistently reproducible)
- Tested on: Physical Android devices (API 30-35) and Android Emulators
- Architecture: Issues 1 & 2 primarily affect Old Architecture; Issue 3 affects both architectures
- All issues occur when using nested stack navigators inside bottom tabs with multi-level navigation
Expected behavior
-
Tab Content Restoration: After navigating to outer stack screens and returning, all tab content should be restored and visible. The navigation state should be preserved and screens should render correctly.
-
Maintained Navigation State: Switching between tabs should maintain each tab's navigation stack. Deep navigation states should persist and render properly when returning to a previously visited tab.
-
Automatic Content Padding: ScrollView and FlatList content should automatically have bottom padding equal to the tab bar height (~56dp), similar to React Navigation's JavaScript bottom tabs. All content should be scrollable and visible without manual padding adjustments.
The native bottom tab navigator should provide the same reliability and UX as JavaScript bottom tabs, with better performance due to native rendering.
Reproduction
https://github.com/yagcismail/navigation-bottom-tab-bug
Platform
- Android
- iOS
- Web
- Windows
- MacOS
Packages
- @react-navigation/bottom-tabs
- @react-navigation/drawer
- @react-navigation/material-top-tabs
- @react-navigation/stack
- @react-navigation/native-stack
- react-native-drawer-layout
- react-native-tab-view
Environment
| package | version |
|---|---|
| @react-navigation/native | 7.1.28 |
| @react-navigation/bottom-tabs | 7.10.0 |
| @react-navigation/drawer | 7.7.13 |
| @react-navigation/stack | 7.6.16 |
| @react-navigation/native-stack | 7.10.1 |
| react-native-screens | 4.18.0 |
| react-native-safe-area-context | 5.4.0 |
| react-native-gesture-handler | 2.25.0 |
| react-native-reanimated | 3.17.4 |
| react-native-pager-view | 6.7.0 |
| react-native | 0.79.3 |
| expo | 53.0.25 |
| node | 18 |
| yarn | - |