nfn
nfn

Reputation: 633

switch navigator in react-navigation v5

There is a good example of switch navigator in V4 documentation of react-navigation:

https://snack.expo.io/@react-navigation/auth-flow-v3

I didn't understand how can I change this into a proper way for V5. here is the link:

https://reactnavigation.org/docs/en/upgrading-from-4.x.html#switch-navigator

Any assistance you can provide would be greatly appreciated.

Upvotes: 0

Views: 17524

Answers (3)

Kavishka Gamage
Kavishka Gamage

Reputation: 122

There is no createSwitchNavigator in React-Navigation v5. So it can be implement as below.

App.js

// login flow
const Auth = createStackNavigator();
const AuthStack =()=> (
    <Auth.Navigator 
        initialRouteName="Login"
        screenOptions={{
          animationEnabled: false
        }}
        headerMode='none'
    >
        <Auth.Screen name="Login" component={LoginScreen} /> 
        <Auth.Screen name="Signup" component={SignupScreen} />
    </Auth.Navigator>
 )

// drawer use only in authenticated screens
const Drawer = createDrawerNavigator();
const DrawerStack = () => (
        <Drawer.Navigator initialRouteName="Home">
            <Drawer.Screen name="Home" component={HomeScreen} />
            <Drawer.Screen name="Settings" component={SettingsScreen} />
            <Drawer.Screen name="Logout" component={LogoutScreen}/>
        </Drawer.Navigator>
)
const RootStack = createStackNavigator();

 class App extends Component {
  constructor() {
    super();
    this.state = {
      loading: true,
      hasToken: false,
    };
  }
 
 componentDidMount(){
    AsyncStorage.getItem('jwtToken').then((token) => {
      this.setState({ hasToken: token !== null,loading:false})
    })
  }

  render() {
    const {loading,hasToken} = this.state;
    
    if (loading) {
      return <WelcomeScreen/>
    } 
   else  {
      return( 
          <NavigationContainer>
              <RootStack.Navigator headerMode="none">
           { !hasToken ? 
              <RootStack.Screen name='Auth' component={AuthStack}/>
           : 
              <RootStack.Screen name='App' component={DrawerStack}/>
           }
           </RootStack.Navigator>
          </NavigationContainer>  
      );
    }
  }
}
export default App;

This is only one way of doing authentication.I haven't use Redux or React Hooks here.You can see the example which used React Hooks in the React Navigation v5 documentation.

Upvotes: 2

big-toni
big-toni

Reputation: 527

I think I found a solution for this issue which will block all unwanted navigation from the user and still keep smooth transitions between screens.

  1. You need to add navigation.service.js like this:
import * as React from 'react';

export const navigationRef = React.createRef();

export const navigate = (routeName, params) => {
  navigationRef.current?.navigate(routeName, params);
}

export const changeStack = (stackName) => {
  resetRoot(stackName)
}

const resetRoot = (routeName) => {
  navigationRef.current?.resetRoot({
    index: 0,
    routes: [{ name: routeName }],
  });
}
  1. add that ref from navigationService to NavigationContainer like this:
<NavigationContainer ref={navigationService.navigationRef}>
  <Navigation />
</NavigationContainer>

now when you know you need to change stack, just call changeStack instead of navigate.

I have explained this solution in more details here: Change stacks in react-navigation v5

Upvotes: 2

Evan
Evan

Reputation: 31

Well, if you want to implement a "switch" like feature with V5, you need to opt into using the new <Stack.Navigator /> definition. Basically, the <Stack.Navigator /> can have children which are <Stack.Screen /> and anytime you explicitly switch between them (or set them to null), it will animate between them. You can find more documentation on how to do this here: https://reactnavigation.org/docs/auth-flow

Upvotes: 3

Related Questions