10

I have 3 tabs and each tab contains a set of stack navigators.

  1. Home Stack
 const HomeNavigator = createStackNavigator(); const HomeStackNavigator = ({navigation, route}) => { return ( <HomeNavigator.Navigator> <HomeNavigator.Screen name="Home" component={Home} /> <HomeNavigator.Screen name="Profile" component={Profile} /> <HomeNavigator.Screen name="Settings" component={Settings} /> </HomeNavigator.Navigator> ); }; 
  1. Store Stack
 const StoreNavigator = createStackNavigator(); const StoreStackNavigator = ({navigation, route}) => { return ( <StoreNavigator.Navigator> <StoreNavigator.Screen name="OurStore" component={Store} /> </StoreNavigator.Navigator> ); }; 
  1. Community Stack
 const CommunityNavigator = createStackNavigator(); const CommunityStackNavigator = ({navigation, route}) => { return ( <CommunityNavigator.Navigator> <CommunityNavigator.Screen name="Community" component={Community} /> <CommunityNavigator.Screen name="CommunityReply" component={CommunityReply} options={communityReplyOptions} /> <CommunityNavigator.Screen name="AskCommunity" component={AskCommunity} /> </CommunityNavigator.Navigator> ); }; 

Tab Navigator

 const MainNavigator = createBottomTabNavigator(); const MainTabNavigator = () => { return ( <MainNavigator.Navigator screenOptions={tabScreenOptions} tabBarOptions={tabBarOptions}> <MainNavigator.Screen name="HomeTab" component={HomeStackNavigator} options={{tabBarLabel: 'Home'}} /> <MainNavigator.Screen name="StoreTab" component={StoreStackNavigator} options={{tabBarLabel: 'Store'}} /> <MainNavigator.Screen name="CommunityTab" component={CommunityStackNavigator} options={{tabBarLabel: 'Community'}} /> </MainNavigator.Navigator> ); }; 

I navigated to CommunityReply Screen which is inside CommunityTab tab from HomeTab by clicking a button using the below approach

props.navigation.navigate('CommunityTab', { screen: 'CommunityReply', params: {postId: postId}, });

It's working fine, when I again come back to CommunityTab it will always be in CommunityReply Screen. How to reset tab stacks when you come back to a CommunityTab tab

React Navigation Versions

"@react-navigation/bottom-tabs": "^5.8.0"

"@react-navigation/native": "^5.7.3"

"@react-navigation/stack": "^5.9.0"

5 Answers 5

30

There is a property called unmountOnBlur designed for this purpose.

https://reactnavigation.org/docs/bottom-tab-navigator#unmountonblur

Changes to make in Tab Navigator :

const MainNavigator = createBottomTabNavigator(); const MainTabNavigator = () => { return ( <MainNavigator.Navigator - screenOptions={tabScreenOptions} + screenOptions={{...tabScreenOptions, unmountOnBlur: true }} tabBarOptions={tabBarOptions}> <MainNavigator.Screen name="HomeTab" component={HomeStackNavigator} options={{tabBarLabel: 'Home'}} /> <MainNavigator.Screen name="StoreTab" component={StoreStackNavigator} options={{tabBarLabel: 'Store'}} /> <MainNavigator.Screen name="CommunityTab" component={CommunityStackNavigator} options={{tabBarLabel: 'Community'}} /> </MainNavigator.Navigator> ); }; 

Summary:
unmountOnBlur: true will solve the problem mentioned.

Sign up to request clarification or add additional context in comments.

4 Comments

Amazingly simple. This is exactly what I was looking for after spending hours googling how to reset nested stack navigators, etc. It also works with Drawer navigators.
Note that this does not work the similar Material components unfortunately
Solution very simple, thank you!
as latest version use popToTopOnBlur:true, instead
8

If you don't want the CommunityReply screen to show when you navigate back to the CommunityTab you need to add an initial option within your navigate function.

props.navigation.navigate( 'CommunityTab', { screen: 'CommunityReply', initial: false, params: { postId: postId }, } ); 

Explained here in the docs

Comments

5

I made a more generic approach to Jeison Guimarães solution (react navigation 6). This approach resets any stack navigation within a tab when the tab index changes. This also makes sure the active stack is not reset when a popover is shown.

<Tab.Screen name="My tab" listeners={resetTabStacksOnBlur} /> 
/** * Resets tabs with stackNavigators to the first route when navigation to another tab */ const resetTabStacksOnBlur = ({navigation}) => ({ blur: () => { const state = navigation.getState(); state.routes.forEach((route, tabIndex) => { if (state?.index !== tabIndex && route.state?.index > 0) { navigation.dispatch(StackActions.popToTop()); } }); }, }); 

2 Comments

Thank you. This solution is more efficient, it doesn't completely unmount stack therefore maintaining performance between tab changes and gives you more control across tabs.
am I understanding this correctly or are you applying the same method to the same stack for each route? navigation object does never change in the loop
1

If the solution above not working for you, try this solution, its work for me.

import { CommonActions } from '@react-navigation/native'; <Tab.Screen listeners={({navigation,route})=>({ blur:()=>{ navigation.dispatch( CommonActions.reset({ index:4, routes:[{name:'Profile'}] }) ) }, })} name="Profile"/> 

2 Comments

Where did index:4 come from? Did you hard-code your nav index?
Tab.Navigator works with a stack that starts from index 0, they are defined by the order you placed, so it’s easy to know which screen index you want, I had 5 tabs and I wanted to get the last one, so I took the from index 4
0

For posterity, if you want to avoid the unmountOnBlur, you can also use the tabPress event (see docs).

The docs in the link above give a nice overview of the default tab press behavior and how to modify it. You can also check out this handy Expo Snack demo.

In particular, to navigate to the initial route on tab press:

function SomeScreen({ navigation }) { useEffect(() => { const unsubscribe = navigation.addListener('tabPress', e => { e.preventDefault(); navigation.navigate('initialRouteName'); }); return unsubscribe; }, [ navigation ]); } 

Bear in mind, if SomeScreen is inside another (nested) navigator, it will be necessary to access the navigation prop from the parent navigator when adding the event listener (navigation.getParent().addListener()).

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.