Search code examples
react-nativereact-navigationreact-navigation-v5

How to define different groups of navigation flow in React-Navigation 5


In pre-5 version of React-Navigation, I use the following JSON style configuration to define multiple navigation flows & embed one flow to the other:

// declare a stack navigator named 'dataListFlow'
const dataListFlow = createStackNavigator({
  DataList: DataListScreen,
  DataDetail: DataDetailScreen,
});

// I use the switch navigator to host two flows: 1. loginFlow 2. mainFlow
const switchNavigator = createSwitchNavigator({
  // 1. loginFlow
  loginFlow: createStackNavigator({
    Signup: SignupScreen,
    Signin: SigninScreen,
  }),

  // 2. mainFlow, NOTE: I embed the dataListFlow into the main flow
  mainFlow: createBottomTabNavigator({
    dataListFlow: dataListFlow,
    dataCreate: dataCreateScreen,
  }),
});

// create the app with the switchNavigator declared above
const App = createAppContainer(switchNavigator);

I would like to implement the same with React-Navigation version 5. I have followed this tutorial to create different navigators with React-Navigation 5, but it only shows how to create each type of navigator separately. I wonder how to implement navigation flows that can be embed into one another like what I have done with the older version react-navigation. Could someone please guide me with some code?


Solution

  • Nothing much has changed actually, the syntax and the way to addressing has changed, So if you see below what i've used is a bottom tab, ive created it separately and now :

    const BottomTab = () => {
      return (
        <Tab.Navigator
          tabBarOptions={{
            activeTintColor: '#fff',
            activeBackgroundColor: '#c47808',
            inactiveBackgroundColor: '#ffbd5c',
            inactiveTintColor: '#c47808',
            style: {
              height: Platform.OS == 'ios' ? hp('10.35%') : hp('8.35%'),
            },
            labelStyle: {
              marginBottom: Platform.OS == 'ios' ? 8 : 2,
            },
          }}
          screenOptions={({route}) => ({
            tabBarIcon: ({focused, color, size}) => {
              return getTabBarIcon(route, focused);
            },
          })}>
          <Tab.Screen name="Home" component={Home} />
          <Tab.Screen name="Meetings" component={Meeting} />
          <Tab.Screen name="My Profile" component={Profile} />
          <Tab.Screen name="Settings" component={Settings} />
        </Tab.Navigator>
      );
    };
    

    Update:

        const HomeTab = () => {
          return (
           <Stack.Navigator
                  initialRouteName="Home"
                  screenOptions={{
                    headerShown: false,
                  }}>
                  <Stack.Screen name="Payment" component={Payment} />
                  <Stack.Screen name="Profile" component={Profile} />
             
                </Stack.Navigator>
          );
        };
    

    if you see how ive included this in my main stack navigator :

        return (
          <NavigationContainer linking={deepLinking}>
            <Stack.Navigator
              initialRouteName="Login"
              screenOptions={{
                headerShown: false,
              }}>
              <Stack.Screen name="Login" component={LoginScreen} />
              <Stack.Screen name="HomeTab" component={HomeTab} />
              <Stack.Screen name="BottomTab" component={BottomTab} />
         
            </Stack.Navigator>
          </NavigationContainer>
        );
    

    i've included it as a simple Stack.Screen and voila it's allscreen are used. Same you can do for if you want to use any other stack navigator and import it as stack.screen inside the main returning compoenent.

    UPDATE:
    
    See above updated stackscreennavigator
    

    hope it helps. feel free for doubts

    UPDATE 2 :

    All my code :

    import React, {Component} from 'react';
    import {
      SafeAreaView,
      StyleSheet,
      ScrollView,
      View,
      Text,
      StatusBar,
      Image,
      Platform,
    } from 'react-native';
    
    import {
      Header,
      LearnMoreLinks,
      Colors,
      DebugInstructions,
      ReloadInstructions,
    } from 'react-native/Libraries/NewAppScreen';
    import {NavigationContainer} from '@react-navigation/native';
    import {createStackNavigator} from '@react-navigation/stack';
    import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
    import LoginScreen from './app/views/auth/LoginScreen';
    import SignupEmail from './app/views/auth/SignupEmailScreen';
    import SignupDetails from './app/views/auth/SignupDetails';
    import Home from './app/views/home/Home';
    import Meeting from './app/views/meetings/Meeting';
    import Profile from './app/views/profile/Profile';
    import Settings from './app/views/settings/Settings';
    import ScheduleMeeting from './app/views/meetings/ScheduleMeeting';
    import MeetCall from './app/views/meet/MeetCall';
    import JitSiCall from './app/views/meet/Jitsi';
    import {
      widthPercentageToDP as wp,
      heightPercentageToDP as hp,
    } from 'react-native-responsive-screen';
    import Webrtc from './app/views/meet/Webrtc';
    
    const Tab = createBottomTabNavigator();
    
    const Stack = createStackNavigator();
    
    // this function gives the icons when tab is selected
    const getTabBarIcon = (route, focused) => {
      const routeName = route.name;
      if (routeName === 'Home') {
        if (focused) {
          return (
            <Image
              style={{height: 22, width: 23}}
              source={require('./app/assets/images/homeF.png')}
            />
          );
        } else {
          return (
            <Image
              style={{height: 22, width: 23}}
              source={require('./app/assets/images/homeUf.png')}
            />
          );
        }
      }
    
      if (routeName === 'Meetings') {
        if (focused) {
          return (
            <Image
              style={styles.imageHeight}
              source={require('./app/assets/images/meetingsF.png')}
              resizeMode="contain"
            />
          );
        } else {
          // console.log(props, 'props');
          return (
            <Image
              style={styles.imageHeight}
              source={require('./app/assets/images/meetingsUF.png')}
              resizeMode="contain"
            />
          );
        }
      }
    
      if (routeName === 'My Profile') {
        if (focused) {
          return (
            <Image
              style={styles.imageHeight}
              source={require('./app/assets/images/profileF.png')}
              resizeMode="contain"
            />
          );
        } else {
          return (
            <Image
              style={styles.imageHeight}
              source={require('./app/assets/images/profileUf.png')}
              resizeMode="contain"
            />
          );
        }
      }
    
      if (routeName === 'Settings') {
        if (focused) {
          return (
            <Image
              style={styles.imageHeight}
              source={require('./app/assets/images/settingsF.png')}
              resizeMode="contain"
            />
          );
        } else {
          return (
            <Image
              style={styles.imageHeight}
              source={require('./app/assets/images/settingsUf.png')}
              resizeMode="contain"
            />
          );
        }
      }
    };
    
    const BottomTab = () => {
      return (
        <Tab.Navigator
          tabBarOptions={{
            activeTintColor: '#fff',
            activeBackgroundColor: '#c47808',
            inactiveBackgroundColor: '#ffbd5c',
            inactiveTintColor: '#c47808',
            style: {
              height: Platform.OS == 'ios' ? hp('10.35%') : hp('8.35%'),
            },
            labelStyle: {
              marginBottom: Platform.OS == 'ios' ? 8 : 2,
            },
          }}
          screenOptions={({route}) => ({
            tabBarIcon: ({focused, color, size}) => {
              return getTabBarIcon(route, focused);
            },
          })}>
          <Tab.Screen name="Home" component={Home} />
          <Tab.Screen name="Meetings" component={Meeting} />
          <Tab.Screen name="My Profile" component={Profile} />
          <Tab.Screen name="Settings" component={Settings} />
        </Tab.Navigator>
      );
    };
    
    class App extends Component {
      render() {
        
        return (
          <NavigationContainer linking={deepLinking}>
            <Stack.Navigator
              initialRouteName="Login"
              screenOptions={{
                headerShown: false,
              }}>
              <Stack.Screen name="Login" component={LoginScreen} />
              <Stack.Screen name="SignupEmail" component={SignupEmail} />
              <Stack.Screen name="SignupDetails" component={SignupDetails} />
              <Stack.Screen name="ScheduleMeeting" component={ScheduleMeeting} />
              <Stack.Screen name="BottomTab" component={BottomTab} />
              <Stack.Screen name="MeetCall" component={MeetCall} />
              <Stack.Screen name="JitSiCall" component={JitSiCall} />
              <Stack.Screen name="Webrtc" component={Webrtc} />
            </Stack.Navigator>
          </NavigationContainer>
        );
      }
    }
    
    const styles = StyleSheet.create({
      scrollView: {
        backgroundColor: Colors.lighter,
      },
      engine: {
        position: 'absolute',
        right: 0,
      },
      body: {
        backgroundColor: Colors.white,
      },
      sectionContainer: {
        marginTop: 32,
        paddingHorizontal: 24,
      },
      sectionTitle: {
        fontSize: 24,
        fontWeight: '600',
        color: Colors.black,
      },
      sectionDescription: {
        marginTop: 8,
        fontSize: 18,
        fontWeight: '400',
        color: Colors.dark,
      },
      highlight: {
        fontWeight: '700',
      },
      footer: {
        color: Colors.dark,
        fontSize: 12,
        fontWeight: '600',
        padding: 4,
        paddingRight: 12,
        textAlign: 'right',
      },
      imageHeight: {
        height: 22,
        width: 20,
        paddingTop: 4,
      },
    });
    
    export default App;