How to hide tabBar in specific Screen in React Navigation 6?
Asked Answered
N

10

7

How to hide tabbar in specific screen in react-navigation 6 ... Without changing navigation structure as it's the only option available in the docs here

Nordin answered 21/12, 2021 at 12:32 Comment(0)
B
7

Sometimes I used this approach

    import { getFocusedRouteNameFromRoute } from ‘@react-navigation/native’;
   

     export const MainNavigator = () => {
      const getTabBarVisibility = (route) => {
        const routeName = getFocusedRouteNameFromRoute(route);
        const hideOnScreens = [SCREENS.REVIEW_ORDER, SCREENS.ORDER_PAYMENT]; // put here name of screen where you want to hide tabBar
        return hideOnScreens.indexOf(routeName) <= -1;
      };
      return (
        <Tab.Navigator>
          <Tab.Screen
            name={SCREENS.ORDER}
            component={OrderNavigator}
            options={({ route }) => ({
              tabBarVisible: getTabBarVisibility(route),
            })}
          />
          <Tab.Screen name={SCREENS.REWARDS} component={SweetRewardsNavigator} />
          <Tab.Screen name={SCREENS.MY_ACCOUNT} component={MyAccountNavigator} />
        </Tab.Navigator>
      );
    };
Bracteate answered 21/12, 2021 at 19:19 Comment(3)
Would you have any idea how to do this when the tabBar is a custom component?Reni
Hi @Reni const focusedOptions = descriptors[state.routes[state.index].key].options; if (focusedOptions.tabBarVisible === false) { return null; } /// TabBar function MyTabBar({ state, descriptors, navigation }) { const focusedOptions = descriptors[state.routes[state.index].key].options; if (focusedOptions.tabBarVisible === false) { return null; } in component that need to hide useEffect(()=>{navigation.setOptions({tabBarVisible:false})},[])Bracteate
This is what I mean https://mcmap.net/q/356927/-react-navigation-5-hide-tab-bar-from-stack-navigatorBracteate
S
2

That's how I made it.

I was looking for a way to hide the tabBar in all my screens on ProductsRoutes, except for the Home screen.(the initial route on the ProductsRoutes Navigator)

Here's the ProductsNavigator:

    const ProductsRoutes = (): JSX.Element => {
      return (
        <Navigator
          initialRouteName="Home"
          screenOptions={{
            headerShown: false,
          }}
        >
          <Screen name="Home" component={Home} />
          <Screen name="Details" component={Details} />
          <Screen name="Cart" component={Cart} />
          <Screen name="Catalog" component={Catalog} />
          <Screen name="Sales" component={Sales} />
          <Screen name="Favorites" component={Favorites} />
        </Navigator>
      );
    };

On my TabRoutes I'm using

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

to know which screen on ProductsNavigator is the Home screen and which one is not. Based on that condition I can set display:'none' or 'display:'flex' to the tabBarStyle prop on Screen props:

import { getFocusedRouteNameFromRoute } from '@react-navigation/native';
    
    const TabRoutes = (): JSX.Element => {
      return (
        <Navigator
          screenOptions={{
            headerShown: false,
          }}
        >
          <Screen
            name="Store"
            component={ProductsRoutes}
            options={({ route }) => {
              const focusedRouteName = getFocusedRouteNameFromRoute(route);
              if (focusedRouteName === 'Home') {
                return {
                  tabBarStyle: { display: 'flex' },
                };
              }
    
              return {
                tabBarStyle: { display: 'none' },
              };
            }}
          />
        </Navigator>
      );
    };

Hope this helps you in some way

Sandstorm answered 11/6, 2022 at 18:19 Comment(0)
N
1

keyword is call setOptions and set tabBarStyle to {display:'none'}

at first, we set id on the parent navigator like

 <Tab.Navigator
      id="tabs"
      tabBar={props => <FooterTabs {...props} style={{display: 'flex'}} />} //<-- add a style with display:flex means tabbar is visible by default
      >
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Search" component={SearchScreen} />
      <Tab.Screen name="Chat" component={ChatScreen} />
    </Tab.Navigator>

suppose we wanna hide the tabbar in ChatScreen

and in ChatScreen, key code like this

const ChatScreen = ({navigation}) => {
  useEffect(() => {
    navigation.getParent('tabs').setOptions({tabBarStyle: {display: 'none'}});
    return ()=>{
    //when leave this screen, and the hooks disposed, we set tabBarStyle to {}, means we will use the default style defined above, that is display:'flex'
 
      navigation.getParent('tabs').setOptions({tabBarStyle: {}});
    };
  }, [navigation]);
...

and you may noticed the tabbar in root tab navigator is a custom component, so inside FooterTabs, key code is like this

const FooterTabs = props => {
  const {state, navigation, descriptors, insets, style} = props;
  const focusedRoute = state.routes[state.index];
  const focusedDescriptor = descriptors[focusedRoute.key];
  const focusedOptions = focusedDescriptor.options;

  const {
    tabBarShowLabel,
    tabBarHideOnKeyboard = false,
    tabBarVisibilityAnimationConfig,
    tabBarStyle, //<-- this is get from options,which we set from sub screens 
    tabBarBackground,
    tabBarActiveTintColor,
    tabBarInactiveTintColor,
    tabBarActiveBackgroundColor,
    tabBarInactiveBackgroundColor,
  } = focusedOptions;

  return (
    <HStack
      style={{...props.style, ...tabBarStyle}} //<-- we set the style over here, so when in some specific screen set tabbarstyle to override the display property to 'none', can final make tabbar hidden
      ...

this above code is get from official bottom tabbar component

Nickola answered 12/9, 2022 at 13:6 Comment(0)
U
1

I created a simple hook for this, works perfect, just call it on any screen useHideBottomBar(); to hide the bottom bar on that screen. Change the styles to match your design.

import React from 'react';
import {useNavigation} from '@react-navigation/native';
import ThemeContext from '../../contexts/ThemeContext';
import useColours from '../useColours';
import {useTheme} from 'react-native-paper';
import {Platform} from 'react-native';
import {themeFontFamily} from '../../helpers/theme';

export function useHideBottomBar() {
  const navigation = useNavigation();
  const {darkMode} = React.useContext(ThemeContext);
  const colours = useColours();
  const theme = useTheme();

  React.useEffect(() => {
    navigation.getParent()?.setOptions({
      tabBarStyle: {display: 'none'},
      tabBarBadgeStyle: {display: 'none'},
    });
    return () =>
      navigation.getParent()?.setOptions({
        tabBarStyle: {
          backgroundColor: darkMode
            ? theme.colors.surface
            : colours.secondary050,
          borderTopColor: darkMode
            ? theme.colors.surfaceVariant
            : colours.secondary200,
          borderTopWidth: 1,
          height: Platform.OS == 'ios' ? 110 : 80,
          display: 'flex',
        },
        tabBarBadgeStyle: {
          ...themeFontFamily.OpenSansSemiBold,
          backgroundColor: colours.errorDark,
          color: colours.white,
          fontSize: 11,
          padding: 0,
          marginTop: 6,
          display: 'flex',
        },
      });
  }, [navigation]);
}
Ulrick answered 1/9, 2023 at 11:5 Comment(0)
I
0
var scroll = 0; // at top

const onScroll = (e: NativeSyntheticEvent<NativeScrollEvent>) => {
    let contentOffsetY = e.nativeEvent.contentOffset.y;
    let diff = contentOffsetY - scroll;
    if (diff < 0) {
      navigation.setOptions({tabBarStyle: {display: 'flex'}});
    } else {
      navigation.setOptions({tabBarStyle: {display: 'none'}});
    }
    scroll = contentOffsetY;
  };

pass this to onScroll of any scrollview component

Incendiary answered 7/9, 2022 at 7:10 Comment(0)
C
0

In my case I had a stack navigator screen in which to hide parent and grandparent navigators' tabBars and headers.

export const MyNav = ({
  route,
  navigation
}) => {

   React.useLayoutEffect(() => {
    
        const routeName = getFocusedRouteNameFromRoute(route);


        if (routeName === 'RouteThatNeedsHiddenTabBarsAndHiddenHeader') {
          navigation.setOptions({ tabBarStyle: { display: 'none' } });
          navigation.getParent()?.setOptions({ headerShown: false });
          navigation.getParent()?.getParent()?.setOptions({ tabBarStyle: { display: 'none' } });
        } else {
          navigation.setOptions({
            tabBarStyle: { ...defaultTabBarStyle, display: 'flex' }
          });
          navigation.getParent()?.setOptions({ headerShown: true });
          navigation.getParent()?.getParent()?.setOptions({ tabBarStyle: {display: 'flex' });
        }
      }, [navigation, route]);

      return (
        <Stack.Navigator>
          <Stack.Screen
            name="NormalRoute"
            component={NormalScreen}
          />
          
          <Stack.Screen
            name="RouteThatNeedsHiddenTabBarAndHiddenHeader"
            component={SpecialScreen}              />
        </Stack.Navigator>
      );
  }

A simpler way if only 1 screen needs to be adjusted would be to run the code in target screen as described here:

https://mcmap.net/q/479533/-how-to-hide-bottom-navigation-bar-on-a-specific-screen-in-react-native

Chuff answered 15/11, 2022 at 20:15 Comment(0)
M
0

For me getFocusedRouteNameFromRoute returned undefined. So I had to implement some other solution. I created navigation named state in redux in which I added property tabBarHidden. Then in tab navigation screen I did this.

const Tab = createBottomTabNavigator();

const MainNavigator = () => {
  const tabBarHidden = useSelector(state => state.navigation.tabBarHidden); <-- redux selector

  return <Tab.Navigator tabBar={props => (
     <View style={{
         display: tabBarHidden ? 'none' : 'flex'
      }}>
       <BottomTabBar {...props} />       <-- imported from @react-navigation/bottom-tabs
     </View>
  )}>
    // your tabs
  </Tab.Navigator>
}

Then you can use redux actions to update the property For example if you want to hide tab bar in chat component you have to do something like

 useFocusEffect( <-- imported from @react-navigation/native
    useCallback(() => {
     dispatch(hideTabBar()) <-- redux action to set tabBarHidden to true

     return () => {
       dispatch(unhideTabBar())
     }
   }, [dispatch]),
 )
Monongahela answered 3/3, 2023 at 10:37 Comment(0)
L
0

I got the solve for this state from React Native Docs and it's work for me👍🏻: Just change your navigation structure.

Example: With this structure👇🏻, when we navigate to the Profile or Settings screen, the tab bar will still stay visible over those screens.

function HomeStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Home" component={Home} />
      <Stack.Screen name="Profile" component={Profile} />
      <Stack.Screen name="Settings" component={Settings} />
    </Stack.Navigator>
  );
}

function App() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeStack} />
      <Tab.Screen name="Feed" component={Feed} />
      <Tab.Screen name="Notifications" component={Notifications} />
    </Tab.Navigator>
  );
}

But if we want to show the tab bar only on the Home, Feed and Notifications screens, but not on the Profile and Settings screens, we'll need to change the navigation structure. The easiest way to achieve this is to nest the tab navigator inside the first screen of the stack instead of nesting stack inside tab navigator: this is the solve👇🏻.

function HomeTabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={Home} />
      <Tab.Screen name="Feed" component={Feed} />
      <Tab.Screen name="Notifications" component={Notifications} />
    </Tab.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeTabs} />
        <Stack.Screen name="Profile" component={Profile} />
        <Stack.Screen name="Settings" component={Settings} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
Lanielanier answered 15/10, 2023 at 14:44 Comment(0)
M
0

This might help if you'r using expo-router and would like to hide tab conditionally.

<MaterialBottomTabs.Screen
  name="admin"
  options={{
     title: `Admin`,
  }}
  redirect={ !isAdmin}
/>
Molton answered 7/9, 2024 at 19:58 Comment(0)
B
0

For React Navigation v5 and v6. You can set a state to hide or show the Tab Navigator.

const [showTab, setShowTab] = useState<boolean>(true);

Then you check for condition to show the tab navigator. <TabNavigator tabBarStyle: { display: showTab ? 'flex' : 'none'/>

Finally, in the screen of interest, you listen for the navigation change

<Tab.Screen
        name={routes.BUY_NAVIGATOR}
        component={BuyNavigator}
        options={{
          tabBarLabel: 'Buy',
          headerShown: false,
          tabBarIcon: ({ color, size }) => <CartIcon color={color} width={30} height={30} />,
          tabBarLabelStyle: {
            marginLeft: 8,
          },
        }}
        listeners={({ route, navigation }) => ({
          
          state: () => {
            const currentRouteName = getFocusedRouteNameFromRoute(route);
            if (currentRouteName === routes.TRADE_CHAT) {
              setShowTab(false);
            } else if (!showTab) {
              setShowTab(true);
            }
          },
        })}
      />
Babul answered 6/10, 2024 at 18:17 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.