switchNavigator with react-navigation 5
Asked Answered
B

5

15

With react-navigation 4, I was able to import and use switchNavigator from "react-navigation" package.

import {
  createAppContainer,
  createSwitchNavigator,
  createStackNavigator
} from "react-navigation";

import MainTabNavigator from "./MainTabNavigator";
import LoginScreen from "../screens/LoginScreen";
import AuthLoadingScreen from "../screens/AuthLoadingScreen";

export default createAppContainer(
  createSwitchNavigator(
    {
      App: MainTabNavigator,
      Auth: AuthLoadingScreen,
      Login: createStackNavigator({ Login: LoginScreen })
    },

    {
      initialRouteName: "Auth"
    }
  )
);

With react-navigation 5, I don't see the createSwitchNavigator in the package anymore. The documentation isn't helpful either. Is the use now not recommended? My use case is to show login screen before user is logged in and switch to the app after user logs in. React-navigation has given an example of authentication flow but is it possible to use switchNavigator - which seems much simpler.

Breathtaking answered 25/2, 2020 at 20:26 Comment(0)
C
24

The switchNavigator was removed because you can do the exact same stuff now with the help of rendering components conditionally.

import React from 'react';
import {useSelector} from "react-redux";
import {NavigationContainer} from "@react-navigation/native";

import { AuthNavigator, MyCustomNavigator } from "./MyCustomNavigator";

const AppNavigator = props => {
    const isAuth = useSelector(state => !!state.auth.access_token);

    return (
        <NavigationContainer>
            { isAuth && <MyCustomNavigator/>}
            { !isAuth && <AuthNavigator/>}
        </NavigationContainer>
    );
};
export default AppNavigator;

The lines inside the NavigationContainer fully replace the old switch navigator.

Cirrate answered 25/2, 2020 at 21:42 Comment(8)
In your example ``` access_token``` would be received (fetch) from server side?Spake
Yes, this token is returned by a server and afterwards saved with redux. But this is independent of the above example. You could use any variable to check which page should be renderd.Cirrate
I got so confused to combine redux, asyncStorage and reactnavigation v5 to persist login details, All tutorials are old, Have you seen any new tutorial?Spake
Then how could we later navigate from a "LoginScreen" (inside AuthNavigator ) to "HomeScreen" (inside MyCustomNavigator )?Sypher
you'd set auth_token using redux from LoginScreenUnadvised
The true/false statement absolutely does not replace the switch navigator. It just assumes that there were previously only two states - which is barmey, as switch statements were never designed to be just binary. This is analogous to removing switch statements from a programming language and forcing developers to rewrite every conditional statement as if/else. Removing a critical piece of functionality that will break existing apps in favor of a simplified design is terrible practice.Decal
@AkinWilliams I dont understand your comment. You are also able to use switch/case inside the Navigation Container.Cirrate
@Cirrate agreed. But this new pattern imposes the following restrictions: 1. significant refactoring of existing code for (imo) little to no benefit, 2. merging the concerns of the navigation function with that of authorization (and any associated function), 3. removing a layer of abstraction that was useful in working with other state containers (like redux).Decal
W
7

I had also used SwitchNavigator of Navigator 4 then after migrating other pages to Navigator 5, i tried to move authentication part to Navigator 5. I could not achieve SwitchNavigator functionality using Navigator 5. Then decided to use "Compatibility layer" provided in Navigation API 5. https://reactnavigation.org/docs/5.x/compatibility
Hope below code will useful for you.

import { createStackNavigator } from '@react-navigation/stack'
import { NavigationContainer } from '@react-navigation/native';
import { createSwitchNavigator } from "@react-navigation/compat";
import { createCompatNavigatorFactory } from '@react-navigation/compat'
 const AppStack = createCompatNavigatorFactory(createStackNavigator)(
      { screen: Home },
      {headerMode:'none'}
 );
 const AuthStack = createCompatNavigatorFactory(createStackNavigator)({ screen:Login });
const SwitchNavigator= createSwitchNavigator(
      {
    Starter: AuthValidation,
    App: AppStack,
    Auth: AuthStack
  },
  {
    initialRouteName:'Starter'
  }
);
export default function App (){
  
    return(
      <NavigationContainer>
          <SwitchNavigator/>
      </NavigationContainer>
    );
}

Here AuthValidation validate for token and depending on value it navigate to "Login" or "Home" Page
_checkAuthetication = async() =>{
  const isUserAuthenticated= await AsyncStorage.getItem("isAuthenticated");
  this.props.navigation.navigate(isUserAuthenticated ? 'App':'Auth');
}
Wysocki answered 14/7, 2020 at 18:46 Comment(0)
O
2

Hey there is no switch navigator in react navigation 5, however you can do this or something on the same lines:

import React, { useEffect } from 'react'
import { StyleSheet, Text, View, ActivityIndicator } from 'react-native'
import { NavigationContainer } from "@react-navigation/native";
import BottomTabsNavigator from './BottomTabsNavigator'
import AccountNavigator from './AccountNavigator'
import firebase from '../api/config'


const SwitchNavigator = ({navigation}) => {
    useEffect(() => {
        firebase.auth().onAuthStateChanged(user => {
            navigation.navigate(user ? "BottomTabsNavigator" : "AccountNavigator")
        })
      }, [])



    return (
        <View style={styles.container}>
            <Text>Loading...</Text>
            <ActivityIndicator size="large" color="#e9446a"></ActivityIndicator>
        </View>
    )
}


const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center'
    }
})

export default SwitchNavigator

and then a Stack Navigator :

import React from 'react'
import { createStackNavigator } from '@react-navigation/stack'
import BottomTabsNavigator from './BottomTabsNavigator'
import AccountNavigator from './AccountNavigator'
import SwitchNavigator from './SwitchNavigator'
import { NavigationContainer } from "@react-navigation/native";

const StackApp = createStackNavigator()

export default function Stack() {
   return (
      <NavigationContainer>
      <StackApp.Navigator initialRouteName='Loading' headerMode='none'>
        <StackApp.Screen name='Loading' component={SwitchNavigator} />
        <StackApp.Screen name='AccountNavigator' component={AccountNavigator}/>
        <StackApp.Screen name='BottomTabsNavigator' component={BottomTabsNavigator}/>
      </StackApp.Navigator>
     </NavigationContainer>

)
}

and then import the Stack navigator into your app.js file like this:

export default App = () => ( <Stack /> )
Orme answered 15/6, 2020 at 21:0 Comment(0)
T
0

This is w.r.t to above query

[Then how could we later navigate from a "LoginScreen" (inside
AuthNavigator ) to "HomeScreen" (inside MyCustomNavigator )? – TalESid
Apr 7 at 8:33 ]
const AuthNavigator = () => {
  return(
  <AuthStack.Navigator>
  <Stack.Screen
    name="Login"
    component={Login}
    options={{ headerShown: false }}
  />
  <Stack.Screen
    name="SignUp"
    component={SignUp}
    options={{ headerShown: false }}
  />
  </AuthStack.Navigator>
);
  }
const MyCustomNavigator = () => {
  return(
  <AppStack.Navigator>
  <Stack.Screen
    name="Home"
    component={Home}
    options={{ headerShown: false }}
  />
  <Stack.Screen
    name="ListScreen"
    component={ListScreen}
    options={{ headerShown: false }}
  />
  <Stack.Screen
    name="Settings"
    component={Settings}
    options={{ headerShown: false }}
  />
  </AppStack.Navigator>
  );
}

const AppNavigator = (props) => {
const isAuth = useSelector((state) => !!state.auth.access_token);

return (
  <NavigationContainer>
    {isAuth && <MyCustomNavigator />}
    {!isAuth && <AuthNavigator />}
  </NavigationContainer>
);
};
export default AppNavigator;
Tote answered 5/7, 2020 at 15:7 Comment(0)
A
0

There isnt a switch navigator in react-navigation v5 or v6. however, i found switch very easy, and i find stack very difficult to use, so i continue to use react-navigation v4.2.0 or 4.4.1, so i can continue using switch

Alienee answered 5/2, 2022 at 14:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.