I am a bit new to react native and I am having difficulty navigate between 2 different tab navigators after login and logout in react native screens of my app that all use function component screens
Can someone advice me on how to do this.
In my Navigation directory(which handle navigation flow), I have 2 files index.js and main.js
- navigation/index.js
- navigation/main.js
Once the user launches the app, the user sees screens in the navigation/index.js file.
After the user either signs up or signs in, the users see screens in the navigation/main.js file
I have implemented everything else in the app except navigate between navigators after login and logout in the app
I initially put all screens in the same navigator file but I started having issues after pressing the back button continuously
see the code below
:::::::::EDITS::::::::::: No longer using Navigation/main.js Now using only Navigation/index.js and implementing what was suggested by @Tolga Berk Ordanuç Still need more help though because It worked partially Now After logging in by clicking login I get the error
" ERROR The action 'NAVIGATE' with payload {"name":"BottomTabNavigator"} was not handled by any navigator.
Do you have a screen named 'BottomTabNavigator'?"
And when I close the app completely by hitting back numerous times, I am logged in But now second error, when I click logout I get below error
ERROR The action 'NAVIGATE' with payload {"name":"Walkthrough"} was not handled by any navigator.
Do you have a screen named 'Walkthrough'?
home.js
import React, {useState} from 'react';
import {View} from 'react-native';
import {useTheme} from '@config';
import {Header, Icon, Button} from '@components';
import {useDispatch} from 'react-redux';
export default function Home({navigation, route}) {
const {colors} = useTheme();
const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const logout = () => {
setLoading(true);
dispatch(setIsLoggedIn(false));
navigation.navigate('SignIn');
setLoading(false);
};
return (
<View style={{flex: 1}}>
<Header
title="sign in"
renderLeft={() => {
return (
<Icon
name="times"
size={20}
color={colors.primary}
enableRTL={true}
/>
);
}}
onPressLeft={() => {
navigation.goBack();
}}
/>
<View>
<Button style={{marginTop: 20}} full loading={loading} onPress={logout}>
Log Out
</Button>
</View>
</View>
);
}
Navigation/main.js
import React from 'react';
import {createStackNavigator} from '@react-navigation/stack';
import {useTheme} from '@config';
import {useSelector} from 'react-redux';
import {designSelect} from '@selectors';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {BaseColor, useFont} from '@config';
import {Icon} from '@components';
/* Main Stack Navigator */
/* Modal Screen only affect iOS */
import Savings from 'Savings';
import Loans from 'Loans';
import Home from 'Home';
import Profile from 'Profile';
/* Stack Screen */
import Setting from 'Setting';
import Feedback from 'Feedback';
import ChangePassword from 'ChangePassword';
import ProfileEdit from 'ProfileEdit';
import ContactUs from 'ContactUs';
import AboutUs from 'AboutUs';
import Support from 'Support';
const MainStack = createStackNavigator();
export default function Main() {
return (
<MainStack.Navigator
screenOptions={{
headerShown: false,
}}
initialRouteName="BottomTabNavigator">
<MainStack.Screen
name="BottomTabNavigator"
component={BottomTabNavigator}
/>
<MainStack.Screen name="Support" component={Support} />
<MainStack.Screen name="SavingsTemp" component={Savings} />
<MainStack.Screen
name="BottomTabNavigator"
component={BottomTabNavigator}
/>
<MainStack.Screen name="Setting" component={Setting} />
<MainStack.Screen name="Feedback" component={Feedback} />
<MainStack.Screen name="ChangePassword" component={ChangePassword} />
<MainStack.Screen name="ProfileEdit" component={ProfileEdit} />
<MainStack.Screen name="ContactUs" component={ContactUs} />
<MainStack.Screen name="AboutUs" component={AboutUs} />
</MainStack.Navigator>
);
}
function BottomTabNavigator() {
const {colors} = useTheme();
const font = useFont();
const BottomTab = createBottomTabNavigator();
const design = useSelector(designSelect);
/**
* Main follow return Home Screen design you are selected
* @param {*} design ['basic', 'real_estate','event', 'food']
* @returns
*/
const exportHome = () => {
return Home;
};
return (
<BottomTab.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: false,
}}
tabBarOptions={{
showIcon: true,
showLabel: true,
activeTintColor: colors.primary,
inactiveTintColor: BaseColor.grayColor,
style: {borderTopWidth: 1},
labelStyle: {
fontSize: 12,
fontFamily: font,
paddingBottom: 4,
},
}}>
<BottomTab.Screen
name="Home"
component={exportHome(design)}
options={{
title: 'home',
tabBarIcon: ({color}) => {
return <Icon color={color} name="home" size={20} solid />;
},
}}
/>
<BottomTab.Screen
name="Savings"
component={Savings}
options={{
title: 'Savings',
tabBarIcon: ({color}) => {
return <Icon color={color} name="bookmark" size={20} solid />;
},
}}
/>
<BottomTab.Screen
name="Loans"
component={Loans}
options={{
title: 'Loans',
tabBarIcon: ({color}) => {
return <Icon color={color} name="clipboard-list" size={20} solid />;
},
}}
/>
<BottomTab.Screen
name="Profile"
component={Profile}
options={{
title: 'Profile',
tabBarIcon: ({color}) => {
return <Icon solid color={color} name="user-circle" size={20} />;
},
}}
/>
</BottomTab.Navigator>
);
}
Navigation/index.js
import React, {useEffect, useState} from 'react';
import {StatusBar, Platform} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import {DarkModeProvider, useDarkMode} from 'react-native-dark-mode';
import {useTheme, BaseSetting} from '@config';
import i18n from 'i18next';
import {initReactI18next} from 'react-i18next';
import {useSelector} from 'react-redux';
import {languageSelect, designSelect} from '@selectors';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {BaseColor, useFont} from '@config';
import {useTranslation} from 'react-i18next';
import {Icon} from '@components';
/* Main Stack Navigator */
/* Modal Screen only affect iOS */
import Loading from 'Loading';
import SignIn from 'SignIn';
import SignUp from 'SignUp';
import ResetPassword from 'ResetPassword';
import Walkthrough from 'Walkthrough';
import Home from 'Home';
import Profile from 'Profile';
import Feedback from 'Feedback';
import ChangePassword from 'ChangePassword';
import ProfileEdit from 'ProfileEdit';
import ContactUs from 'ContactUs';
import AboutUs from 'AboutUs';
import Tab2 from 'Tab2';
import Tab3 from 'Tab3';
import BottomTabNavigator from './BottomTabNavigator';
import {store} from '../store';
const RootStack = createStackNavigator();
export default function Navigator() {
const language = useSelector(languageSelect);
const {theme, colors} = useTheme();
const isDarkMode = useDarkMode();
const [isLoggedInValue, setIsLoggedInValue] = useState(false);
useEffect(() => {
i18n.use(initReactI18next).init({
resources: BaseSetting.resourcesLanguage,
lng: language ?? BaseSetting.defaultLanguage,
fallbackLng: BaseSetting.defaultLanguage,
});
if (Platform.OS === 'android') {
StatusBar.setBackgroundColor(colors.primary, true);
}
StatusBar.setBarStyle(isDarkMode ? 'light-content' : 'dark-content', true);
console.log('<<<<< IS LOGGED IN STATE >>>>>>');
console.log(isLoggedInValue);
console.log('<<<<< IS LOGGED IN STATE >>>>>>');
setIsLoggedInValue(store.getState().isloggedin.isLoggedIn);
}, [colors.primary, isDarkMode, language, isLoggedInValue]);
return (
<DarkModeProvider>
<NavigationContainer theme={theme}>
<RootStack.Navigator
mode="modal"
screenOptions={{
headerShown: false,
}}>
{!isLoggedInValue ? (
<>
<RootStack.Screen
name="Loading"
component={Loading}
options={{gestureEnabled: false}}
/>
<RootStack.Screen name="Walkthrough" component={Walkthrough} />
<RootStack.Screen name="SignIn" component={SignIn} />
<RootStack.Screen name="SignUp" component={SignUp} />
<RootStack.Screen
name="ResetPassword"
component={ResetPassword}
/>
</>
) : (
<>
<RootStack.Screen
name="BottomTabNavigator"
component={BottomTabNavigator}
/>
<RootStack.Screen name="Feedback" component={Feedback} />
<RootStack.Screen
name="ChangePassword"
component={ChangePassword}
/>
<RootStack.Screen name="ProfileEdit" component={ProfileEdit} />
<RootStack.Screen name="ContactUs" component={ContactUs} />
<RootStack.Screen name="AboutUs" component={AboutUs} />
</>
)}
</RootStack.Navigator>
</NavigationContainer>
</DarkModeProvider>
);
}
Signin.js
import React, {useState} from 'react';
import {
View,
TouchableOpacity,
KeyboardAvoidingView,
Platform,
Alert,
} from 'react-native';
import {useDispatch} from 'react-redux';
import {BaseStyle, useTheme} from '@config';
import {Header, SafeAreaView, Icon, Text, Button, TextInput} from '@components';
import styles from './styles';
export default function SignIn({navigation, route}) {
const {colors} = useTheme();
const [loading, setLoading] = useState(false);
const [id, setId] = useState('');
const [password, setPassword] = useState('');
const dispatch = useDispatch();
/**
* call when action onLogin
*/
const onLogin = () => {
setLoading(true);
dispatch(setIsLoggedIn(true));
navigation.navigate('Home');
setLoading(false);
};
const offsetKeyboard = Platform.select({
ios: 0,
android: 20,
});
return (
<View style={{flex: 1}}>
<Header
title="sign in"
renderLeft={() => {
return (
<Icon
name="times"
size={20}
color={colors.primary}
enableRTL={true}
/>
);
}}
onPressLeft={() => {
navigation.goBack();
}}
/>
<SafeAreaView style={BaseStyle.safeAreaView} edges={['right', 'left']}>
<KeyboardAvoidingView
behavior={Platform.OS === 'android' ? 'height' : 'padding'}
keyboardVerticalOffset={offsetKeyboard}
style={{flex: 1}}>
<View style={styles.contain}>
<TextInput onChangeText={setId} placeholder="username" value={id} />
<TextInput
style={{marginTop: 10}}
onChangeText={setPassword}
placeholder="Password"
secureTextEntry={true}
value={password}
/>
<Button
style={{marginTop: 20}}
full
loading={loading}
onPress={onLogin}>
'sign_in'
</Button>
<TouchableOpacity
onPress={() => navigation.navigate('ResetPassword')}>
<Text body1 grayColor style={{marginTop: 25}}>
'forgot_your_password'
</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
</View>
);
}
5
navigation/BottomTabNavigator.js
export default function BottomTabNavigator() {
const {colors} = useTheme();
const font = useFont();
const design = useSelector(designSelect);
const BottomTab = createBottomTabNavigator();
const exportHome = () => {
return Home;
};
return (
<BottomTab.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: false,
}}
tabBarOptions={{
showIcon: true,
showLabel: true,
activeTintColor: colors.primary,
inactiveTintColor: BaseColor.grayColor,
style: {borderTopWidth: 1},
labelStyle: {
fontSize: 12,
fontFamily: font,
paddingBottom: 4,
},
}}>
<BottomTab.Screen
name="Home"
component={exportHome(design)}
options={{
title: 'Home',
tabBarIcon: ({color}) => {
return <Icon color={color} name="home" size={20} solid />;
},
}}
/>
<BottomTab.Screen
name="Savings"
component={Tab2}
options={{
title: 'Savings',
tabBarIcon: ({color}) => {
return <Icon color={color} name="bookmark" size={20} solid />;
},
}}
/>
<BottomTab.Screen
name="Loans"
component={Tab3}
options={{
title: 'Loans',
tabBarIcon: ({color}) => {
return <Icon color={color} name="clipboard-list" size={20} solid />;
},
}}
/>
<BottomTab.Screen
name="Profile"
component={Profile}
options={{
title: 'Profile',
tabBarIcon: ({color}) => {
return <Icon solid color={color} name="user-circle" size={20} />;
},
}}
/>
</BottomTab.Navigator>
);
}