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
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>
);
};
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
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
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]);
}
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
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
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]),
)
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>
);
}
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}
/>
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);
}
},
})}
/>
© 2022 - 2025 — McMap. All rights reserved.