Vineel
Vineel

Reputation: 265

How to reset tab stack when you come back to a tab from another tab react navigation v5

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"

Upvotes: 10

Views: 16528

Answers (5)

Przemyslaw
Przemyslaw

Reputation: 752

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()).

Upvotes: 0

Bob
Bob

Reputation: 51

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());
      }
    });
  },
});

Upvotes: 5

Etienne Tonnelier
Etienne Tonnelier

Reputation: 2239

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.

Upvotes: 29

Jackson
Jackson

Reputation: 141

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

Upvotes: 8

Jeison Guimar&#227;es
Jeison Guimar&#227;es

Reputation: 51

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"/>

Upvotes: 1

Related Questions