10

I have a TabNavigator as shown in the picture. Header Image

I am using TabNavigator for creating these tabs as below.

const Tab_Navigator = TabNavigator({
    First:{
        screen: First,
    },
    Second:{
        screen: Second,
    },
    Third:{
        screen: Third,
    },

Now I want to block/disable "Second" and "Third" tabs. It should be visible but one shouldn't able to navigate to them.

I tried blocking these tabs as shown here but I guess I am missing something. My try:

Tab_Navigator.router.getStateForAction = (action, state) => {
if( action.type === NavigationActions.navigate({ routeName: "Second"}) ||
    action.type === NavigationActions.navigate({ routeName: "Third"}))
{
    return null;
}

return Byte.router.getStateForAction(action, state);

};

Smit Thakkar
  • 410
  • 2
  • 8
  • 16

4 Answers4

15

In this case, the action.type = "Navigation/NAVIGATE" and action.routeName is the name of your tab. It is just a little different from the ReactNavigation Routers example. The following should work:

const defaultGetStateForAction = Tab_Navigator.router.getStateForAction;

Tab_Navigator.router.getStateForAction = (action, state) => {
  if ((action.type === NavigationActions.NAVIGATE) &&
     (action.routeName === "Second" || action.routeName === "Third") {
    return null;
  }

  return defaultGetStateForAction(action, state);
};

EDIT: Here is an image of the the Chrome Debugger stopped at a breakpoint in a very similar piece of code(tab names are different), but it shows the values of the "action" object being passed into this function. react native router disable tab

Jeremy Schrader
  • 386
  • 1
  • 11
  • @JeremySchrader can you tell pls also how to remove tabs dynamically? – Alexander Danilov Mar 12 '18 at 04:05
  • I can't get this solution to work (even though it's included in the official documentation at https://reactnavigation.org/docs/en/routers.html#blocking-navigation-actions) and I'm baffled. By contrast I'm finding that returning null from tabBarOnPress, as suggested by Asif below, does block navigation. However I'm trying to create a block that's conditional on previous route (which needs the state information available in getStateForAction) but returning null from getStateForAction is having no effect. Any clues on how I can proceed, or debug further? – Michael O'Connor Aug 01 '19 at 22:05
  • To answer my own question above: I've found I have to create a StackNavigator for each of the screens in my Tab_Navigator (with each StackNavigator containing one screen) and then use this list of StackNavigators in my Tab_Navigator instead of the list of screens. I don't know why this works, but it allows getStateForAction to block navigation actions (which doesn't work otherwise). – Michael O'Connor Aug 02 '19 at 17:54
5

For Version 5.x+ there's a new way to do it.

<Tabs.Screen
  name="Chat"
  component={Chat}
  listeners={{
    tabPress: e => {
      // Prevent default action
      e.preventDefault();
    },
  }}
/>

Here's the reference link to the docs: https://reactnavigation.org/docs/navigation-events/

NemyaNation
  • 983
  • 1
  • 12
  • 22
4

This is my solution to disable and completely take control over the tabBarButton in React Navigation 6.

// Defining the disabled tabBarButton component
//
const DisabledTabBarButton = ({ style, ...props }: BottomTabBarButtonProps) => (
  <Pressable disabled style={[{ opacity: 0.2 }, style]} {...props} />
)

const Tab = createBottomTabNavigator()

const Router = () => (
<Tab.Navigator>
  <Tab.Screen name="Screen 1" />
  <Tab.Screen name="Screen 2"
    options={{
      // Applying the disabled button
      tabBarButton: DisabledTabBarButton,
    }}
  />
</Tab.Navigator>

export default Router
Jimmi Jønsson
  • 129
  • 1
  • 4
3

You have to use tabBarOnPress propert under defaultNavigationOptions, and check the route name to which you dont want to navigate return them null else return defaultHandler. Please check the following code

const Tab_Navigator = createBottomTabNavigator({
   First:{
        screen: First,
    },
    Second:{
        screen: Second,
    },
    Third:{
        screen: Third,
    }
}, defaultNavigationOptions: ({ navigation }) => ({
      tabBarOnPress: ({ navigation, defaultHandler }) => {
        if (
          navigation.state.routeName === "Second" ||
          navigation.state.routeName === "Third"
        ) {
          return null;
        }
        defaultHandler();
      },})
Penny Liu
  • 15,447
  • 5
  • 79
  • 98