Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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>
  ;
like image 292
Jonis Maurin Ceará Avatar asked Jun 04 '20 21:06

Jonis Maurin Ceará


2 Answers

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.

like image 52
Fabio Dias Avatar answered Nov 10 '22 13:11

Fabio Dias


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

like image 31
Gaurav Prabhu Avatar answered Nov 10 '22 15:11

Gaurav Prabhu