Skip to content
Advertisement

React Navigation TabNavigator: Reset previous tab on tab change

I have the following route structure:

StackNavigator
-StackNavigator
-TabNavigator
--Tab1
---Route 1 (Stack) (initial)
---Route 2 (Stack)

--Tab2
---Route 3 (Stack) (initial)
---Route 4 (Stack)

When I visit Tab1 -> Route 1 -> Route 2 -> Tab2 and go back to Tab1, the active route is 2 instead of the initialRoute 1.

I’m doing the following:

tabBarOnPress: ({ scene }) => {
    const { route } = scene;
    const tabRoute = route.routeName;
    const { routeName } = route.routes[0];

    navigation.dispatch(NavigationActions.navigate({ routeName: tabRoute }));

    navigation.dispatch(NavigationActions.reset({
        index: 0,
        actions: [
            NavigationActions.navigate({ routeName }),
        ],
    }));
},

but the problem is that it first shows Route 2 and then navigate to Route 1.

How can I reset the previous tab/screens, so when I switch the tab always to show directly the initial route.

Advertisement

Answer

Solution for version 5.x.x and version 6.x.x:

Pass a listener to the screen component:

<Tab.Screen
     name="homeTab"
     component={HomeStackScreen}
     listeners={tabBarListeners}
/>

Then on this listener, navigate the user every time when he presses the tab:

const tabBarListeners = ({ navigation, route }) => ({
    tabPress: () => navigation.navigate(route.name),
});

Credits: https://github.com/react-navigation/react-navigation/issues/8583

Solution for version 4.x.x:

tabBarOnPress: ({ navigation }) => {
  navigation.popToTop();
  navigation.navigate(navigation.state.routeName);
}

Credits: https://github.com/react-navigation/react-navigation/issues/1557

Solution for versions 2.x.x and 3.x.x:

The problem is that when I reset the route, I need to pass the navigation action of the previous routeName (leaving tab) and to dispatch a new navigation action for the next route:

tabBarOnPress: ({ previousScene, scene }) => {
    const tabRoute = scene.route.routeName;
    const prevRouteName = previousScene.routes[0].routeName;

    navigation.dispatch(NavigationActions.reset({
        index: 0,
        actions: [
            NavigationActions.navigate({
                routeName: prevRouteName
            }),
        ],
    }));

    navigation.dispatch(NavigationActions.navigate({
        routeName: tabRoute
    }));
}
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement