I am building an app with React Native and Expo and i am trying to implement authentication in the app but i am getting this error and i can’t find a solution.
Basically i have 2 navigation stacks AppStack
& AuthStack
in my App.js
. AppStack
will be shown if the user is authenticated and if the user is not authenticated then AuthStack
will be shown to the user.
So i am conditionally rendering the stacks with ternary operator as you can see in the App.js code below. The stacks are working fine i mean if user is authenticated then AppStack
is shown and if not then AuthStack
is shown.
Now the Signin screen is present in AuthStack
and when a user logs in successfully he should be navigated to Home screen navigation.navigate("Home")
which is present in AppStack
. But when a user logs in it throws me this error.
ERROR The action 'NAVIGATE' with payload {"name":"Home"} was not handled by any navigator.
Do you have a screen named 'Home'?
If you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator.
This is a development-only warning and won't be shown in production
Here is the App.js code:
const AppStack = () => {
return (
<>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} options={{headerStyle: {backgroundColor: "#000"}, headerTintColor: "white"}} />
<Stack.Screen name="Forgot Password" component={ForgotPwd} options={{headerStyle: {backgroundColor: "#2a454e"}, headerTintColor: "white"}} />
<Stack.Screen name="Check Your Inbox" component={ForgotPwdNext} options={{headerStyle: {backgroundColor: "#00dfc0"}, headerTintColor: "#3a5864"}} />
<Stack.Screen name="Change Password" component={ChangePwd} options={{headerStyle: {backgroundColor: "#e5322b"}, headerTintColor: "white"}} />
</Stack.Navigator>
</>
)
}
const AuthStack = () => {
return (
<>
<Stack.Navigator>
<Stack.Screen name="Welcome" component={Welcome} options={{headerStyle: {backgroundColor: "#1b4152"}, headerTintColor: "white"}} />
<Stack.Screen name="Signin" component={Signin} options={{headerStyle: {backgroundColor: "#5549ab"}, headerTintColor: "white"}} />
<Stack.Screen name="Signup" component={Signup} options={{headerStyle: {backgroundColor: "#26dec0"}, headerTintColor: "#35474f"}} />
<Stack.Screen name="Verify Phone Number" component={VerifyPhone} options={{headerStyle: {backgroundColor: "#d268cc"}, headerTintColor: "white"}} />
<Stack.Screen name="Logged Out" component={LoggedOut} options={{headerStyle: {backgroundColor: "#5a6e7f"}, headerTintColor: "white"}} />
</Stack.Navigator>
</>
)
}
return (
<NavigationContainer style={styles.root}>
<StatusBar style="light" />
{isAuthenticated ? <AppStack /> : <AuthStack />}
</NavigationContainer>
)
}
3
Answers
somehow managed to solve the error by registering AppStack as a screen in AuthStack and also registering AuthStack as screen in AppStack like this:
NOTE THE LAST SCREEN IN AppStack ABOVE
And same with the AppStack
But now the problem is i am getting 2 navigation headers When i switch between screens which are in different stacks i mean if i go from one screen to another which are both in same stack then 2 headers doesn't appear, 2 headers only appear when i go from a screen which is in suppose Stack-A to Stack-B
You cannot navigate from
Signin
toHome
. You can only navigate between screens that share a parent navigator or grandfather if you have nested navigators. Here is a quote from the doc talking about this specific navigator they created:The common way is to have a way to change
isAuthenticated
to true inSignin
instead of navigating, and the below condition inApp.js
will do the job. For that you can pass a state setter fromApp
toSignin
using acontext
for example.This exact problem is addressed here.
Your
AuthStack
doesn’t know anything aboutAppStack
and vice versa. Hencenavigation.navigate("Home")
fromAuthStack
will fail.When
isAuthenticated
is changed React Navigation will automatically navigate to correct screen. This is possible whenisAuthenticated
state is managed globally using React Context (or by using any state management library like Redux, Zustand etc).Check this official example which more or less resembles your authentication flow.