user3601578
user3601578

Reputation: 1362

Reset stack navigation when tab button is pressed in ReactNav 5

I have 3 tabs and behind each tab is a stack navigation. I always want to reset the stack navigation when I click on another tab button.

Right now, when I go in Stack1 like A -> B -> C -> D and I change to Tab2 and then change back to Tab1, I am again at Screen D. I want to see Screen A again. I use React-Navigation-5

I would accept any answer that shows me a piece of code how to implement that.

My code looks like this:

App.js:

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="Tab1" component={Stack1} />
        <Tab.Screen name="Tab2" component={Stack2} />
        <Tab.Screen name="Tab3" component={Stack3} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

where as each of my stack navigations look like this:

function EventExploreStack({ navigation }) {  
  return (
    <SettingsStack.Navigator initialRouteName="A">
      <SettingsStack.Screen name="A" component={AScreen} />
      <SettingsStack.Screen name="B" component={BScreen} />
      <SettingsStack.Screen name="C" component={CScreen} />
      <SettingsStack.Screen name="D" component={DScreen} />
      <SettingsStack.Screen name="E" component={EScreen} />
    </SettingsStack.Navigator>
  );
}

export default EventExploreStack;

I am using React Navigation 5.

Upvotes: 0

Views: 2171

Answers (3)

Rolando Niub&#243;
Rolando Niub&#243;

Reputation: 1215

Create a helper that reset the stacks of all Tabs that are not currently selected, and pass it to every tab.

Like this:

Helper:

import { StackActions } from '@react-navigation/native';

export const resetStacksOnTabClicks = ({ navigation }: any) => ({
    tabPress: (e: any) => {
        const state = navigation.dangerouslyGetState();
        if (state) {
            const nonTargetTabs = state.routes.filter((r: any) => r.key !== e.target);
            nonTargetTabs.forEach((tab: any) => {
                if (tab?.state?.key) {
                    navigation.dispatch({
                        ...StackActions.popToTop(),
                        target: tab?.state?.key,
                    });
                }
            });
        }
    },
});

Then pass that helper to every Tab in the listeners prop like this:

    <Tabs.Screen
      name="TabName"
      component={YourComponent}
      listeners={resetStacksOnTabClicks}
    />

Upvotes: 0

dilbert_murthy
dilbert_murthy

Reputation: 36

Take a look at the **createBottomTabNavigator** here https://reactnavigation.org/docs/bottom-tab-navigator/

Example

npm install @react-navigation/bottom-tabs

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const Tab = createBottomTabNavigator();

function MyTabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Settings" component={SettingsScreen} />
    </Tab.Navigator>
  );
}

Upvotes: 0

Guruparan Giritharan
Guruparan Giritharan

Reputation: 16354

One option would be to use the reset action of the navigation. As you are having three stacks in three tabs you will need a custom tabbarbutton to do this which will reset the state of the given tab. The code for the button will be as below.

Here I've used Home and Settings as tabs, you will have to change them to your need.

const CustomButton = (props) => {
  const navigation = useNavigation();
  return (
    <TouchableOpacity
      {...props}
      onPress={() => {
        navigation.dispatch((state) => {
          const newState = Object.assign(state);
          const index = newState.routes.findIndex((x) => (x.name = 'Home'));

          if (newState.routes[index].state) {
            const { name, key } = newState.routes[index];
            newState.routes[index] = { name, key };
          }

          return CommonActions.reset({
            ...newState,
          });
        });
        navigation.navigate('Settings');
      }}
    />
  );
};

Which you can place in the tab screen as below

<Tab.Screen
    name="Settings"
    component={SettingsScreen}
    options={{
      tabBarButton: (props) => <CustomButton {...props} />,
   }}
  />

You can tryout the sample here https://snack.expo.io/@guruparan/bottomnavclick

Hope this helps :)

Upvotes: 2

Related Questions