How to hide Drawer item in react-navigation 5x?
Asked Answered
A

2

7

I'm trying to create a Drawer navigation in my app using react-navigation, but I'm having difficult to hide one item. What I want: create some screens (to navigate inside app), but NOT display those screens in Drawer. I'm using this doc: (https://reactnavigation.org/docs/nesting-navigators/#navigator-specific-methods-are-available-in-the-navigators-nested-inside)

But I have two problems: 1) Root still being displayed; 2) I can't navigate direct to 'hidden' screen, it says that screen doesn't exist.

This is my current code:

const Stack = createStackNavigator();
function Root2() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="NewEditPilot" component={NewEditPilot} />
      <Stack.Screen name="Settings" component={Settings} />
    </Stack.Navigator>
  );
}


const Drawer = createDrawerNavigator();

function MyDrawer() {
  return (
    <Drawer.Navigator drawerContent={props => <SideBar2 {...props} />}>
      <Drawer.Screen name="Home" component={Home} />
      <Drawer.Screen name="PilotMgnt" component={PilotMgnt} />
      <Drawer.Screen name="Root2" component={Root2} />
    </Drawer.Navigator>
  );
}


export default function App() {


  return (
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <Root>
          <NavigationContainer>
            <MyDrawer />
          </NavigationContainer>
        </Root>
      </PersistGate>
    </Provider>
  );
}

In this case, I'm trying to hidde NewEditPilot and Settings screens. This is how I was navigating to these screens: navigation.navigate('NewEditPilot') (this was working on react-navigation 4x).

Also, this is how I was using (and working!) in react-navigation 4x:

// Telas principais
const Drawer = DrawerNavigator(
  {
    Home: { screen: Home },
    PilotMgnt: { screen: PilotMgnt},
    CurRace: { screen: CurRace},
    Settings: { screen: Settings},        
    LogViewScreen: { screen: LogViewScreen},    
  },
  {
    initialRouteName: "Home",
    contentOptions: {
      activeTintColor: "#e91e63"
    },
    contentComponent: props => <SideBar {...props} />
  }
);

// sub-telas
const AppNavigator = StackNavigator(
  {
    Drawer: { screen: Drawer },    
    NewEditPilot: { screen: NewEditPilot },
    PersonalRank: { screen: PersonalRank },  
    RCharts: { screen: RCharts},
    RChartsArchive: { screen: RChartsArchive},
    Archive: { screen: Archive },
    ArchiveView: { screen: ArchiveView },
    ArchivePersonalRank: { screen: ArchivePersonalRank },
  },
  {
    initialRouteName: "Drawer",
    headerMode: "none"
  }
);




export default () =>
    <Provider store={store}>
      <PersistGate loading={null} persistor={persistor}>
        <Root>
          <AppNavigator />
        </Root>
      </PersistGate>
    </Provider>
  ;
Aureus answered 4/6, 2020 at 21:1 Comment(0)
S
1

In your Sidebar2 component you can chose to create a custom <DrawerContentScrollView /> which will have <DrawerItem />. These <DrawerItem /> would be those items that you want to be made visible in the drawer. navigation prop is passed by default to the drawerContent component. You can use this navigation prop to navigate to a particular screen using navigation.navigate('Screen_Name'). Make sure there is a <Drawer.Screen> available for the route where you want to navigate.

https://reactnavigation.org/docs/drawer-navigator#providing-a-custom-drawercontent

Shamblin answered 7/6, 2020 at 21:53 Comment(0)
A
9

I just manage to solve this properly, with some help from this issue.

To proper hide an item you should make an function that filters the routes, and pass it to the drawerContent prop of Drawer.Navigator.

Let's assume that you want to hide the Login Screen from your Drawer, but you still want to be able to navigate to it, whenever you want, you should do something like this:

import {
  createDrawerNavigator,
  DrawerContentScrollView,
  DrawerItemList,
} from '@react-navigation/drawer';

const Drawer = createDrawerNavigator();
    
const CustomDrawerContent = (props) => {
    const { state, ...rest } = props;
    const newState = { ...state };
    newState.routes = newState.routes.filter(
      (item) => item.name !== 'Login',
    );
    
    return (
      <DrawerContentScrollView {...props}>
        <DrawerItemList state={newState} {...rest} />
      </DrawerContentScrollView>
    );
  };
    
  export default () => (
    <Drawer.Navigator
      initialRouteName="Home"
      drawerContent={(props) => <CustomDrawerContent {...props} />}
      screenOptions={{
        headerShown: true,
      }}>
       <Drawer.Screen
         name="Home"
         component={HomeScreen}
         options={{ title: 'Home' }}
       />
        .
        .
        .

Hope this helps, cheers.

Aplanospore answered 8/9, 2020 at 17:44 Comment(1)
This is a great solution and very flexible. I also use this as a workaround if I want to hide the bottom tab bar for some screens, I just add that screen to the list of drawer items, hide them filtering out that route and works perfectly!Tolerance
S
1

In your Sidebar2 component you can chose to create a custom <DrawerContentScrollView /> which will have <DrawerItem />. These <DrawerItem /> would be those items that you want to be made visible in the drawer. navigation prop is passed by default to the drawerContent component. You can use this navigation prop to navigate to a particular screen using navigation.navigate('Screen_Name'). Make sure there is a <Drawer.Screen> available for the route where you want to navigate.

https://reactnavigation.org/docs/drawer-navigator#providing-a-custom-drawercontent

Shamblin answered 7/6, 2020 at 21:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.