I am getting the above error. I am quite a aware it is an issue with my nested navigation, however I have looked through a lot of questions as well as the official documentation and I have not been able to figure out what I am doing wrong.
This is my navigation file:
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import HomeScreen from '../screens/HomeScreen';
import ProfileScreen from '../screens/ProfileScreen';
import SettingsScreen from '../screens/SettingsScreen';
import SignInScreen from '../screens/SignInScreen';
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
const HomeStack = () => {
return (
<Stack.Navigator>
<Stack.Screen name="HomeScreen" component={HomeScreen} />
<Stack.Screen name="ProfileScreen" component={ProfileScreen} />
</Stack.Navigator>
);
};
const RootNavigator = () => {
const [isAuthenticated, setIsAuthenticated] = React.useState(false);
return (
<NavigationContainer>
{isAuthenticated ? (
<Tab.Navigator>
<Tab.Screen name="HomeScreen" component={HomeStack} />
<Tab.Screen name="SettingsScreen" component={SettingsScreen} />
</Tab.Navigator>
) : (
<Stack.Navigator>
<Stack.Screen name="SignInScreen" component={SignInScreen} />
</Stack.Navigator>
)}
</NavigationContainer>
);
};
export default RootNavigator;
I am calling the navigate function from my signin screen:
const handleSignInPress = () => {
if (emailError || passwordError) {
return;
}
navigation.navigate('HomeScreen');
};
The HomeScreen looks like this:
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { useNavigation } from '@react-navigation/native';
interface HomeScreenProps {
targetDate: Date;
}
const HomeScreen: React.FC<HomeScreenProps> = () => {
const [timeLeft, setTimeLeft] = React.useState(calculateTimeLeft());
const navigation = useNavigation();
function calculateTimeLeft() {
const targetDate = new Date('May 28, 2023');
const difference = targetDate.getTime() - new Date().getTime();
let timeLeft = {};
if (difference > 0) {
timeLeft = {
days: Math.floor(difference / (1000 * 60 * 60 * 24)),
hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
minutes: Math.floor((difference / 1000 / 60) % 60),
seconds: Math.floor((difference / 1000) % 60),
};
}
return timeLeft;
}
React.useEffect(() => {
const timer = setInterval(() => {
setTimeLeft(calculateTimeLeft());
}, 1000);
return () => clearInterval(timer);
}, []);
const { days, hours, minutes, seconds } = timeLeft;
return (
<View style={styles.container}>
<Text style={styles.title}>Countdown Timer</Text>
<Text style={styles.timer}>
{days}d {hours}h {minutes}m {seconds}s
</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 16,
},
timer: {
fontSize: 48,
fontWeight: 'bold',
},
});
export default HomeScreen;
I am not sure where the issue is. The code checks out and is very similar to other examples I have seen online.
If anyone could explain to me what is going on and how I can fix it, that would be super helpful as I am just getting started in React Native.
2
Answers
The issue may be that you’re simply not changing isAuthenticated.
Is there any other logic in that handleSignInPress function?
Once you add the logic to handle isAuthenticated’s change to true, the ‘navigation’ will happen automatically because once it changes to true, your home stack will be rendered and login stack won’t.
I hope this helps.
If there
What happens is, that the navigation object you are using to navigate, has the context of that stack that the screen is defined in. That means you can’t directly navigate different stacks like this, they are two different entities. There are two ways to do it.
First is to put them both inside one common navigator so that you can navigate between them, but the easier one is just to set the prop of authorized navigator:
that way, when you authorize, it will render a second navigator, and it will render the screen with the name defined inside initialRouteName prop. If no initialRouteName is defined, I think it will fallback to the first child in it