17

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.

3
  • I'm busy atm, thus making only a comment. But google for jumpToIndex, it's a prop of TabBar which can also be used for reseting the stack. Commented Jan 29, 2018 at 16:06
  • You can check out my answer to a very similar question here: stackoverflow.com/a/48446647/2805067 Commented Feb 1, 2018 at 13:15
  • Does this answer your question? React Native Navigation: Reset Stack Navigator Commented Feb 8, 2021 at 4:36

3 Answers 3

17

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
    }));
}
Sign up to request clarification or add additional context in comments.

Comments

7

use unmountOnBlur option it works for all types of navigators , stack navigator , drawer navigator , bottomtab navigator

<Tab.Screen name="Home" component={DrawerNavigator} options={{unmountOnBlur:true}}/>

pass unmountOnBlur in the options prop of the screen of the navigator

5 Comments

Worked really well for me. Why there are no upvotes? Are there drawbacks to this solution?
@SergeyYarotskiy There is a comment,Normally, we don't recommend enabling this prop as users don't expect their navigation history to be lost when switching tabs. If you enable this prop, please consider if this will actually provide a better experience for the user. at official page(stackoverflow.com/questions/61611483/…)
But this would be a good answer, simple and easy.
I tried this and it causes flickering of the tab when switching tabs. And also it breaks the stack if you navigated to a nested screen from another stack. Then with this option enabled the stack always starts on the nested screen when changing tabs. So indeed there are serious drawbacks unfortunately.
@Episodex : I also found the flickering effect when switching between the tabs, if we give unmountonBlur:true which is very annoying . But at the same time , i need to re-render each tab when i press tabicon each time. Do you have any solution for this?
0

You can give a try with reset props like this :

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

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

Edit : If this doesn't solve the issue you can check this github issue with some workarounds

2 Comments

Unfortunately, it doesn't work. It threw an error: There is no route defined for key Tab2. Must be one of: 'Route 1', 'Route 2'. It appears if I directly click on the second tab.
It was a while ago, but I think this worked: stackoverflow.com/a/68788917/219547 . I commented that something was wrong there but I see in the code it works like this currently. One change is dangerouslyGetState to just getState(). It was also important to not use NativeStackNavigator but StackNavigator to avoid flickering.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.