Hi I am trying to add Tab Navigation when user is logged in and Stack Navigation when User is not logged in. So I have wrote a logic but I don't know why I am getting errors. Kindly help me out.
I wanted to show Tab Navigation only when user has successfully logged in I am using Nodejs backend and Mongodb as database.
This is my AppNavigator file.
AppNavigator.js
import React, { useEffect, useState } from "react"; import { createStackNavigator } from "@react-navigation/stack"; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' import { NavigationContainer } from '@react-navigation/native'; import SignUp from "../screens/SignupScreen"; import LoginScreen from "../screens/LoginScreen"; import LoadingScreen from "../screens/LoadingScreen"; import HomeScreen from "../screens/HomeScreen"; import AsyncStorage from '@react-native-async-storage/async-storage'; const Stack = createStackNavigator(); const Tab = createBottomTabNavigator() const [isLoggedin, setLogged] = useState(null) const TabNavigator = () => { return <TabNavigator> <Tab.Screen name='Home' component={HomeScreen} /> <Tab.Screen name='Profile' component={AccountScreen} /> <Tab.Screen name='Home' component={HomeScreen} /> </TabNavigator> } const AuthNavigator = () => { return ( <Stack.Navigator headerMode="none" screenOptions={{ headerStyle: { elevation: 0 }, cardStyle: { backgroundColor: '#fff' } }} > <Stack.Screen name="loading" component={LoadingScreen}></Stack.Screen> <Stack.Screen name="home" component={HomeScreen}></Stack.Screen> <Stack.Screen name="login" component={LoginScreen}></Stack.Screen> <Stack.Screen name="signup" component={SignUp}></Stack.Screen> </Stack.Navigator> ) }; const Navigation = () => { const [user, setUser] = useState(''); useEffect(() => { if (isLoggedin) { setUser(userExist) } else { setUser('') } }, []) return ( <NavigationContainer > {user? <TabNavigator />: <AuthNavigator />} </NavigationContainer> ) }; function AppNavigator() { useEffect(() => { const token = AsyncStorage.getItem('token') if (token) { setLogged(true) } else { setLogged(false) } }, []) return ( <Navigation /> ); } export default AppNavigator;
This is my App.js file
App.js
import React,{useEffect,useState} from "react"; import { NavigationContainer } from "@react-navigation/native"; import AppNavigator from "./navigation/AppNavigator"; export default function App() { return ( <AppNavigator /> ); }
I have my own LoadingScreen file
LoadingScreen.js
import { StatusBar } from 'expo-status-bar'; import React,{useEffect,useState} from 'react'; import { StyleSheet, ActivityIndicator, Image,View,Text } from 'react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { Button, TextInput } from 'react-native-paper'; // <View style={styles.container}> export default function LoadingScreen(props) { const detectLogin = () =>{ const token = AsyncStorage.getItem('token') if (token) { props.navigation.navigate("profile") } else { props.navigation.navigate("login") } } useEffect(() => { detectLogin() }, []) return ( <View style={styles.container}> <ActivityIndicator size="large" color="black"> </ActivityIndicator> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, });
I've created a Snack for you to see the working example
The first thing that I Noticed is that in your TabNavigator
function you wrote
return <TabNavigator>
<Tab.Screen name='Home' component={HomeScreen} />
<Tab.Screen name='Profile' component={AccountScreen} />
<Tab.Screen name='Home' component={HomeScreen} />
</TabNavigator>
Instead you have to write something like this
return <Tab.Navigator> // Notice the . here
<Tab.Screen name='Home' component={HomeScreen} />
<Tab.Screen name='Profile' component={AccountScreen} />
<Tab.Screen name='Home' component={HomeScreen} />
</Tab.Navigator>
Your token restoration logic is not efficient I guess.
I would suggest you to make two different Navigators
and perform token checking
logic inside your App.js
What you should do is, create a folder called navigation
where your App.js
is located.
Then inside navigation
create two files AppNavigator.js
and AuthNavigator.js
Your AppNavigator.js
should look like this -
import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import HomeScreen from '../screens/HomeScreen';
import AccountScreen from '../screens/AccountScreen';
const Tab = createBottomTabNavigator();
function AppNavigator() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Accounts" component={AccountScreen} />
</Tab.Navigator>
);
}
export default AppNavigator;
Your AuthNavigator.js
should look like this -
import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import LoadingScreen from '../screens/LoadingScreen';
import HomeScreen from '../screens/HomeScreen';
import LoginScreen from '../screens/LoginScreen';
import SignUp from '../screens/SignUpScreen';
const Stack = createStackNavigator();
function AuthNavigator() {
return (
<Stack.Navigator
headerMode="none"
screenOptions={{
headerStyle: { elevation: 0 },
cardStyle: { backgroundColor: '#fff' },
}}>
<Stack.Screen name="loading" component={LoadingScreen}></Stack.Screen>
<Stack.Screen name="home" component={HomeScreen}></Stack.Screen>
<Stack.Screen name="login" component={LoginScreen}></Stack.Screen>
<Stack.Screen name="signup" component={SignUp}></Stack.Screen>
</Stack.Navigator>
);
}
export default AuthNavigator;
Then you should install expo-app-loading
from here
Then in your App.js
import React, { useEffect, useState } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import AppLoading from 'expo-app-loading';
import AsyncStorage from '@react-native-async-storage/async-storage';
import AppNavigator from './navigation/AppNavigator';
import AuthNavigator from './navigation/AuthNavigator';
export default function App() {
const [user, setUser] = useState('');
const [IsReady, setIsReady] = useState(false);
const RestoreUser = async () => {
const token = await AsyncStorage.getItem('token');
if (token) {
setUser(true);
} else {
setUser(false);
}
};
if (!IsReady) {
return (
<AppLoading
startAsync={RestoreUser}
onFinish={() => setIsReady(true)}
onError={() => {}}
/>
);
}
return (
<NavigationContainer>
{user ? <AppNavigator /> : <AuthNavigator />}
</NavigationContainer>
);
}
This is the most efficient way of authentication that I use in all my projects..
Apparently I have to remove these two from my code in order to work correctly, it's resolved now. Thankyou.
import { StatusBar } from 'expo-status-bar'; <StatusBar style="dark" backgroundColor="black" barStyle="light-content" />
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.