25

I am using React Native and React Native Navigation to build out my application. Currently, I have three bottom tabs: Home, Upload Video and Messages. Upon selection of the Upload Video tab, I want to render the Upload Video component and hide the bottom tabs on just that screen, and display a header with 'Cancel' (takes them back to the HomeView) and 'Post' buttons (this has already been done). I've had an extremely difficult time hiding the tab bar on this specific screen.

I tried following the code here (How can I hide the bottom tab bar on a specific screen (react-navigation 3.x)); however, that ended up being unsuccessful and I was not able to hide the bottom tabs on any of the screens this way.

Currently, I have this as my bottom navigator:

const BottomTabNavigator = createBottomTabNavigator({
    HomeView: {
        screen: HomeView,
    },
    VideoView: {
        screen: VideoSelectionView
    },
    Messages: {
        screen: SearchView
    }
});

Any insight would be extremely helpful, thanks.

dmouawad
  • 539
  • 1
  • 5
  • 13

11 Answers11

28

I've traversed the internet like never before to find a solution for this problem as the provided solution by the docs did not work in the slightest.

I had the following navigational Set-Up:

  • Bottom Tabs
    • A (NativeStack)
      • 1 (Screen)
      • 2 (Screen)
      • 3 (Screen)
    • B (NativeStack)
    • C (NativeStack)

I wanted to hide the bottom bar in Screen 1. What finally did the trick was the following snippet in the corresponding screen:

  useEffect(() => {
    navigation.getParent()?.setOptions({
      tabBarStyle: {
        display: "none"
      }
    });
    return () => navigation.getParent()?.setOptions({
      tabBarStyle: undefined
    });
  }, [navigation]);

The effect is run when the navigation prop updates and with that implicitly after the screen is being opened. With getParent() I get the bottom tabs navigator and can set the options with setOptions(...). To bring the bottom tabs back one has to manually set the options. I solved this by returning the method that resets the tabBarStyle in the call of useEffect(). This call is being made when it's time to clean-up, meaning that it will run as soon as the screen is being unmounted.

May this save same of you of the desperation I had to go through.

danklad
  • 88
  • 8
Escaper
  • 441
  • 5
  • 6
  • 1
    You are my favourite person in the world right now – ellipticaldoor Dec 28 '21 at 11:51
  • 1
    In my case it was navigation.setOptions() and not the parent – FR073N Mar 22 '22 at 09:38
  • It does work but is completely counter intuitive and will mess up the navigation structure – Maximilian Dietel May 07 '22 at 07:03
  • Wouldn't have figured this in a million years (@FR073N's fix actually worked)! – roshnet Aug 25 '22 at 09:58
  • With your current code snippet I am just seeing a white background where the tabs would be. however, if I put use the display: none inside a setTimout of 500 ms it works with a delay? Wondering if you or anyone else experienced this. – max Nov 08 '22 at 03:44
  • @max No, I have not experienced that, so I am not sure what could cause this unfortunately. Have you tried the same code snippet, with and without the getParent() option like FR073N suggested it? I could imagine, that the approach with the setTimeout might result in a jumpy UI. – Escaper Nov 12 '22 at 10:33
  • @max i have the same issue. At first when i save the file the bottom bar disappears, then i move back to the parent and when i move again to the screen, the bar is not there but then i have a "padding" just as the height of the bar. Even if i refresh the app, the "padding" is still there. It works again if i change the code inside the useEffect. For example i change display: "none" to "flex" and then to "none" again, save... it works, and then after i switch to another tab and back, i have the "padding" all the time. Any fix for this? – Ilir Nov 30 '22 at 00:56
  • I experienced the same problem, for me it was only on IOS. This was my solution ```if (Platform.OS === "ios") { enableScreens(false); }``` – Moemen Hussein Mar 06 '23 at 14:29
  • You should use that in a useFocusEffect because in a useEffect if you navigate to another screen the component won't unmount and you won't have the bottom tabs on other screens. – yoann84 Apr 27 '23 at 16:07
  • @MoemenHussein would you mind elaborating on your solution? Facing the same issue right now on IOS, but not sure where to put the code you shared. Should I just put it at the top of the useEffect? Thanks for sharing your solution though! – seth8656 May 16 '23 at 15:18
  • @seth8656 I have put it in `app.js` in the useEffect(). And try to restart your app afterwards – Moemen Hussein May 17 '23 at 18:22
15

You need to specify for each TabBar screen or stack for which you need to hide tabbar,

const BottomTabNavigator = createBottomTabNavigator({
    HomeView: {
        screen: HomeView,
        navigationOptions:()=>{
          return {
            tabBarVisible:false,
          };
       }
    },
    VideoView: {
        screen: VideoSelectionView
    },
    Messages: {
        screen: SearchView
    }
});
Jaydeep Galani
  • 4,842
  • 3
  • 27
  • 47
5

Just setting the tabBarStyle to none doesn't work for me, I needed to use the property tabBarVisible too, if using hooks you can do something like that:

export function useHideBottomBar() {
    const navigation = useNavigation();

    useEffect(() => {
        navigation.getParent()?.setOptions({ tabBarStyle: { display: 'none' }, tabBarVisible: false });
        return () =>
            navigation.getParent()?.setOptions({ tabBarStyle: undefined, tabBarVisible: undefined });
    }, [navigation]);
}
Kalebe Samuel
  • 111
  • 1
  • 5
3

In React Navigation V6 add display: none in options under tabBarStyle. Add tabBarButton: () => null, to disable icon in Tab.

<Stack.Screen
    name="Add Product"
    component={AddProduct}
    options={() => ({
      tabBarStyle: {
        display: "none",
      },
      tabBarButton: () => null,
    })}
  />
Farhaan
  • 160
  • 2
  • 4
2

on v5 you can modify options using a function and default arg navigation.:

<BottomTab.Screen
      name="Explore"
      component={Explore}
      options={({ navigation }) => {
        const { routes, index } = navigation.dangerouslyGetState();
        const { state: exploreState } = routes[index];
        let tabBarVisible = true;
        if (exploreState) {
          const { routes: exploreRoutes, index: exploreIndex } = exploreState;
          const exploreActiveRoute = exploreRoutes[exploreIndex];
          if (exploreActiveRoute.name === "RewardDetail") tabBarVisible = false;
        }
        return {
          tabBarVisible,
          title: "Explore",
          tabBarLabel: "Explore",
          tabBarIcon: ({ color, size }) => (
            <AntDesign name="search1" color={color} size={size} />
          ),
        };
      }}
    />

see my answer: https://stackoverflow.com/a/64042879/5288560

gpbaculio
  • 5,693
  • 13
  • 60
  • 102
1

Since react-navigation 5 is now being used, the above solution doesn't work anymore.

For React-Navigation 5, refer to this link.

R.K
  • 1,721
  • 17
  • 22
1

In Version 6 this worked for me:

To hide the bottom tab navigator from the screen:

navigation.getParent()?.setOptions({tabBarStyle: {display: 'none'}});

To show the bottom tab navigator from the screen:

navigation.getParent()?.setOptions({tabBarStyle: {display: 'flex'}});
Zach Jensz
  • 3,650
  • 5
  • 15
  • 30
Uzzam Altaf
  • 303
  • 4
  • 8
0

In React navigation 5+ I used the following approach to hide a tab bar on a specific screen which was inside a stack navigator of a tab screen. In my tab navigator containing file I made a function, and then set the options property using the function which will trigger dynamically.

function getIsTabBarShown(route) {
    const routeName = getFocusedRouteNameFromRoute(route) ?? routes.DASHBOARD;

    switch (routeName) {
        case routes.MEMBERDETAILS:
            return false;
        default:
            return true;
    }
}

This function will return false when user would go to MemberDetails Page which is inside MemberNavigator Stack.

<Tab.Screen 
    name="MemberTab"
    component={MemberNavigator}
    options={({ route }) => ({
        title: 'Members',
        tabBarVisible: getIsTabBarShown(route),
        tabBarIcon: ({ color, size }) =>
        <MaterialCommunityIcons name="account-group" color={color} 
   size={size} />
})} />

Here is the official docs to learn more click here.

Robin Khan
  • 127
  • 1
  • 10
0

After searching and trying a lot of methods I changed the top element View to Modal then hid bottombar, because modal can be upper bottom bar. It's not the best but still useful.

<View>
  //code block
</View> 

to->
         
<Modal animationType='fade' transparent={false} visible={true}>
   /code block
</Modal>
Zach Jensz
  • 3,650
  • 5
  • 15
  • 30
Zafer ATLI
  • 41
  • 2
0

In version 6+ this resolve my problem

<Tab.Screen
    name="Profile"
    component={Profile}
    options={{ tabBarButton: (props) => null }}
  />
-2

just on the Screen you want to hide the bar, set tabBarVisible: false.

<Tab.Screen
    name="SignIn"
    component={SignInScreen}
    options={{
      tabBarVisible: false, //like this
      tabBarButton: (props) => null, //this is additional if you want to hide the tab element from the bottom nav
    }}
  />
shiraz27
  • 1,898
  • 18
  • 14