'How to set always first screen of Stack Navigator inside Tab Navigator React Navigation 5

React Navigation 5

I've build a StackNavigator inside of a TabNavigator, and the navigation between home screen and other screens is working. But the problem is,When I move from Tab2 to Tab1 I expect Tab1 always show me first screen of StackNavigator.

tab1
   -> Stack
        -screen1
        -screen2
tab2

I am on screen2 and then move to tab2 after that then I move back to Tab1 I want to always display screen1.

I am try to use

OnTabPress({navigation})=>{
    navigation.navigate("stackName",{
     screen: "screen1"
   }).
}

Its work but its show me screen2 first then navigate to screen1. Is there any other Solution. https://snack.expo.io/@usamasomy/groaning-donut



Solution 1:[1]

Use unmountOnBlur: true in options. Eg.

<Tab.Screen
        name="Stack1"
        component={Stack1}
        options={{
          tabBarLabel: "Stack1",
          unmountOnBlur: true,
        }}
      />

So when you are navigating away from this tab and you're on screen2 of Stack1, you will always come on the first screen of this stackNavigator when coming back to this tab.

Solution 2:[2]

enter image description here

initialRouteName= "NAME" is the keyword to make sure you have a default and make sure you use navigate() push() pop() accordingly.

Firstly, create a custom TabBar so we can write our own functions executed by onPress

function MyTabBar({ state, descriptors, navigation }) {
  return (
    <View style={{ flexDirection: 'row' }}>
      {state.routes.map((route, index) => {
        const { options } = descriptors[route.key];
        const label =
          options.tabBarLabel !== undefined
            ? options.tabBarLabel
            : options.title !== undefined
            ? options.title
            : route.name;

        const isFocused = state.index === index;

        const onPress = () => {
            navigation.reset({
              index: 0,
              routes: [{ name: 'Screen1' }],
            }) 

        if (!isFocused && !event.defaultPrevented) {
            navigation.navigate(route.name);
          }      
            }}
        const onLongPress = () => {
          navigation.emit({
            type: 'tabLongPress',
            target: route.key,
          });
        };

Then in the TabScreens override the original TabBar in Tab.Navigator by using tabBar=... then call navigation.reset() with index:0 and routes:{{name: 'Screen1'}} every time MyTabBar is pressed.

const TabScreens = ()=>{
  return(
    <Tab.Navigator  tabBar={props => <MyTabBar {...props} />} initialRouteName="Tab1Screens" >
      <Tab.Screen 
        name      = "Tab1Screens"
        component = {Tab1Screens}
      />
      <Tab.Screen
        name      = "Tab2Screens"
        component = {Tab2Screens}
      />
    </Tab.Navigator>
  )
}

        return (
          <TouchableOpacity
            accessibilityRole="button"
            accessibilityStates={isFocused ? ['selected'] : []}
            accessibilityLabel={options.tabBarAccessibilityLabel}
            testID={options.tabBarTestID}
            onPress={onPress}
            onLongPress={onLongPress}
            style={{ flex: 1 }}
          >
            <Text style={{ color: isFocused ? '#673ab7' : '#222' }}>
              {label}
            </Text>
          </TouchableOpacity>
        );
      })}
    </View>
  );
}

This can be greatly improved eg:

-some logic before `navigation.reset()`

-Accessing onPress without creating a new component 

-etc..

finally snack available here :https://snack.expo.io/@karammarrie/customtabbar

Solution 3:[3]

i have a simple solution is to set initialRouteName= "screen1" in

<Stack.Navigator
      screenOptions={{
        headerShown: false,
      }}
      initialRouteName="screen1"
    >
      <Stack.Screen name="screen1" component={Screen1} />
      <Stack.Screen name="screen2" component={Screen2} />
</Stack.Navigator>

   {/** **/}

if the screen still shows the first screen 2, you just need to comment the line <Stack.Screen name="screen2" component={Screen2} /> and reload the screen, then remove the comment line.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Abhishek Shakya
Solution 2
Solution 3