I've followed the documentation for creating bottom tab navigation with react-navigation v5 ("@react-navigation/native": "^5.2.3")
Currently is partially used this example in my project from docs https://reactnavigation.org/docs/bottom-tab-navigator/ to fit the needs of version 5.
Example might be following
// Navigation.tsx
import { BottomTabBarProps } from '@react-navigation/bottom-tabs';
import { TabActions } from '@react-navigation/native';
import * as React from 'react';
function Navigation({ state, descriptors, navigation }: BottomTabBarProps) {
return (
<View>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const isFocused = state.index === index;
const onPress = () => {
const event = navigation.emit({
type: 'tabPress',
target: route.key,
canPreventDefault: true,
});
if (!isFocused && !event.defaultPrevented) {
const jumpToAction = TabActions.jumpTo(options.title || 'Home');
navigation.dispatch(jumpToAction);
}
};
return (
<TouchableOpacity
key={options.title}
accessibilityLabel={options.tabBarAccessibilityLabel}
accessibilityRole="button"
active={isFocused}
activeOpacity={1}
testID={options.tabBarTestID}
onPress={onPress}
>
{route.name}
</TouchableOpacity>
);
})}
</View>
);
}
export default Navigation;
However, I have a couple of nested StackNavigators as described in AppNavigator.tsx
AppNavigator.tsx
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import React from 'react';
import { AppState, AppStateStatus } from 'react-native';
import Navigation from '../components/navigation/Navigation';
import AccountScreen from '../screens/account';
import SettingsScreen from '../screens/settings';
import SupportScreen from '../screens/support';
import HomeNavigator from './HomeNavigator';
import TransactionNavigator from './TransactionNavigator';
const { Navigator, Screen } = createBottomTabNavigator();
const AppNavigator = () => {
return (
<View>
<Navigator tabBar={(props) => <Navigation {...props} />}>
<Screen
component={HomeNavigator}
name="Home"
options={{ title: 'Home' }}
/>
<Screen
component={TransactionNavigator}
name="Transactions"
options={{
title: 'Transactions' }}
/>
<Screen
component={AccountScreen}
name="Account"
options={{ title: 'Account' }}
/>
<Screen
component={SupportScreen}
name="Support"
options={{ title: 'Support' }}
/>
<Screen
component={SettingsScreen}
name="Settings"
options={{
title: 'Settings' }}
/>
</Navigator>
</View>
);
};
export default AppNavigator;
And I am aiming for resetting the nested StackNavigator each time user leaves it. So example can be HOME -> TRANSACTIONS -> TRANSACTION_DETAIL (which is part of a nested navigator) -> HOME -> TRANSACTIONS
currently, I see a TRANSACTION_DETAIL after the last step of the "walk through" path. Nevertheless, I want to see TRANSACTIONS instead. I found that if I change
if (!isFocused && !event.defaultPrevented) {
const jumpToAction = TabActions.jumpTo(options.title || 'Home');
navigation.dispatch(jumpToAction);
}
to
if (!isFocused && !event.defaultPrevented) {
navigation.reset({ index, routes: [{ name: route.name }] });
}
it more or less does the thing. But it resets the navigation, so it is unmounted and on return back, all data are lost and need to refetch.
In navigation is PopToTop() function that is not available in this scope.
Also I tried to access all nested navigators through descriptors, yet I have not found how to correctly force them to popToTop.
And the idea is do it on one place so it will be handled automatically and there would not be any need to implement it on each screen.