Search code examples
javascriptreactjsreact-nativenavigationtabbar

How to add two screens to the navigation of the React Native app without showing them in the TabBar?


I need the user registration and login screens to not be displayed in the TabBar of the App I have a simple application in which I am trying to have two types of user interface, one for a guest mode and one for when the user is authenticated. I have created a navigation for each authentication conditional, so that the TabBar corresponding to each state of the application is displayed, or guest mode or authenticated mode. I also have a TabBar Component to show the Icons of each of the Navigations.

The problem arises when I want to add the LoginScreen and RegisterScreen screens since I can't access them.

I have tried to create a third Navigation (AuthNavigator ) to manage these screens, and finally got access but they show up on the TabBar, But this cannot be, these screens cannot be accessed from the TabBar

I need them to be in the navigation, but not show on the TabBar.

In the TabBar file these screens are not added, so the Icon is not shown, but the title is

I have tried using options={{ tabBarVisible: false }} , but this has no effect

Also display = "none" without success.

I have looked for solutions in Google and I have not found anything.

I want to show my navigation system to guide me what I'm doing. wrong and can correct my mistakes.

--------- App.js ---------

import React from 'react'
import { NavigationContainer } from '@react-navigation/native'
import GuestNavigator from './navigation/GuestNavigator'
import AppNavigator from './navigation/AppNavigator'

const App = () => {
 
  const isUserAuthenticated = false; 

  return (
    <NavigationContainer>
      {isUserAuthenticated ? (
        <AppNavigator />
      ) : (
        <GuestNavigator />
      )}
    </NavigationContainer>
  )
}
export default App 

---This is the navigation in GUEST mode---

---- GuestNavigator.JS -------

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import TabBar from '../components/TabBar';

const Tab = createBottomTabNavigator();

const GuestNavigator = ({ handleLogin }) => {
  return (
    <Tab.Navigator tabBar={props => <TabBar {...props} />}>
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="SampleNotas" component={SampleNotasScreen} />
      <Tab.Screen name="SampleCuras" component={SampleCurasScreen} />
      <Tab.Screen name="SamplePerfil" component={SamplePerfilScreen} />
      <Tab.Screen
        name="Login"
        options={{ tabBarVisible: false }}
        children={() => <LoginScreen handleLogin={handleLogin} />}
      />
    </Tab.Navigator>
  );
};
export default GuestNavigator; 

--This is the navigation in the AUTHENTICATED mode --

------ AppNavigator.JS ---------

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import TabBar from '../components/TabBar';
const Tab = createBottomTabNavigator();

const AppNavigator = () => {
  return (
    <Tab.Navigator tabBar={props => <TabBar {...props} />}>
      <Tab.Screen name="Notas" component={NotasScreen} />
      <Tab.Screen name="CrearNota" component={CrearNotaScreen} options={{ tabBarVisible: false }} />
      <Tab.Screen name="Curas" component={CurasScreen} />
      <Tab.Screen name="Recordatorios" component={RecordatoriosScreen}/>
      <Tab.Screen name="Profile" component={ProfileScreen} />
      <Tab.Screen name="EditProfile" component={EditarProfileScreen} options={{ tabBarVisible: false }} />
    </Tab.Navigator>
  );
};
export default AppNavigator

And I have also created a navigation system only for Login and Register

------- AuthNavigator.js ----------

import React from 'react'
import { NavigationContainer } from '@react-navigation/native'
import { createStackNavigator } from '@react-navigation/stack'
import LoginScreen from '../screens/AuthScreens/LoginScreen'
import RegisterScreen from '../screens/AuthScreens/RegisterScreen'

const Stack = createStackNavigator()

const AuthNavigator = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="Login"
          component={LoginScreen}
          options={{
            headerShown: false,
          }}
        />
        <Stack.Screen
          name="Register"
          component={RegisterScreen}
          options={{
            title: 'Registro',
          }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  )
}

export default AuthNavigator

Of course if I remove LoginScrein from the GuestNavigator navigation, I get error:

ERROR The action 'NAVIGATE' with payload {"name":"Login"} was not handled by any navigator. Do you have a screen named 'Login'? If you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator. This is a development-only warning and won't be shown in production.

And I also show the TabBar although it shows the icon and these screens are not added. ----- TabBar.js -----------

import React from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';

const TabBar = ({ state, descriptors, navigation, isUserAuthenticated }) => {
  return (
    <View style={{ flexDirection: 'row', height: 60, backgroundColor: '#F3F9F5' }}>
      {state.routes.map((route, index) => {
        const { options } = descriptors[route.key];

        const onPress = () => {
          const event = navigation.emit({
            type: 'tabPress',
            target: route.key,
          });

          if (!event.defaultPrevented) {
            navigation.navigate(route.name);
          }
        };

        const isFocused = state.index === index;
        const color = isFocused ? '#08A438' : 'black';

        let iconName;
        if (!isUserAuthenticated) {
          // Iconos para el modo invitado
          if (route.name === 'Home') {
            iconName = 'home';
          } else if (route.name === 'SampleNotas') {
            iconName = 'list';
          } else if (route.name === 'SampleCuras') {
            iconName = 'medkit';
          } else if (route.name === 'SamplePerfil') {
            iconName = 'person';
          }
        } else {
          // Iconos para el modo autenticado
          if (route.name === 'Notas') {
            iconName = 'notes';
          } else if (route.name === 'Curas') {
            iconName = 'medkit';
          } else if (route.name === 'Recordatorios') {
            iconName = 'alarm';
          } else if (route.name === 'Profile') {
            iconName = 'person';
          }
        }

        return (
          <TouchableOpacity
            key={index}
            onPress={onPress}
            style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}
          >
            <Icon name={iconName} size={24} color={color} />
            <Text style={{ color }}>{route.name}</Text>
          </TouchableOpacity>
        );
      })}
    </View>
  );
};
export default TabBar

Solution

  • to resolve this add Guestnavigator to AuthNavigator like this:

    const AuthNavigator = ({}) => {
      return (
        <Stack.Navigator>
          <Stack.Screen name="GuestStack" component={GuestNavigator}/>
          <Stack.Screen name="Login" component={LoginScreen}/>
          <Stack.Screen name="Register" component={RegisterScreen}/>
       </Stack.Navigator>
      );
    };
    

    refactor App.js to:

    const App = () => {    
      return (
        <NavigationContainer>
          {isAuth ? <AuthNavigator /> : <AppNavigator />}
        </NavigationContainer>
      )
    }
    

    and don't forget to remove the login tab from GuestNavigator.