How to go back to another stack in react native navigation v5? - javascript

I want to navigate to Home Details which is in HomeStack , from About component which is in AboutStack :
HomeStack.js
export default function HomeStack() {
return (
<Stack.Navigator>
<Stack.Screen component={Home} name="Home" />
<Stack.Screen component={HomeDetail} name="HomeDetail" />
</Stack.Navigator>
);
}
AboutStack.js
export default function AboutStack() {
return (
<Stack.Navigator>
<Stack.Screen component={About} name="About" />
<Stack.Screen component={AboutDetail} name="AboutDetail" />
</Stack.Navigator>
);
}
In About component I navigate to the HomeDetails screen which is in HomeStack navigator :
About.js
<Button
title="Go Home details"
onPress={() => navigation.navigate('HomeStack', { screen: 'HomeDetail' })} />
And in HomeDetail screen I try to go back which should go back to the About screen in AboutStack but it goes to Home screen in HomeStack:
HomeDetail.js
<Button onPress={() => navigation.goBack()} title="Go back" />
It goes back to the root screen of it's own Stack .
This is the navigation version I'm using:
"#react-navigation/native": "^5.8.10",
"#react-navigation/stack": "^5.12.8",
How can I go back to About screen in About Stack from HomeDetails screen in HomeStack ?

I solved the problem by passing url params to HomeDetail screen like this :
About.js
navigation.navigate('HomeDetail', { url: 'About' })
HomeDetail.js
function HomeDetail({ navigation, route }) {
console.log(route);
return (
<View style={{ marginTop: 300 }}>
<Text>Home Detail</Text>
<Button onPress={() => navigation.navigate(route.params.url)} title="Go back" />
</View>
);
}

Related

ERROR The action 'NAVIGATE' with payload {"name":"Home"} was not handled by any navigator

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>
)
}
This exact problem is addressed here.
Your AuthStack doesn't know anything about AppStack and vice versa. Hence navigation.navigate("Home") from AuthStack will fail.
When isAuthenticated is changed React Navigation will automatically navigate to correct screen. This is possible when isAuthenticated 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.
You cannot navigate from Signin to Home. 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:
Said another way, we can only navigate to routes that have been defined on our navigator — we cannot navigate to an arbitrary component
The common way is to have a way to change isAuthenticated to true in Signin instead of navigating, and the below condition in App.js will do the job. For that you can pass a state setter from App to Signin using a context for example.
{isAuthenticated ? <AppStack /> : <AuthStack />}
somehow managed to solve the error by registering AppStack as a screen in AuthStack and also registering AuthStack as screen in AppStack like this:
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.Screen name="AuthStack" component={AuthStack} />
</Stack.Navigator>
</>
)
}
NOTE THE LAST SCREEN IN AppStack ABOVE
And same with the AppStack
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.Screen name="AppStack" component={AppStack} />
</Stack.Navigator>
</>
)
}
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

The development server returned response error code: 500 {react Native}

I was setting up the navigations in my App.Js while encountered this error and I am completely clueless that how to solve this issue. Can someone help me?
And just pasting the code of App.Js
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import Home from "../screens/Home";
import Login from "../screens/Login";
import Registeration from "../screens/Registeration";
function HomeScreen({ navigation }) {
return (
<View >
<Home />
<Button
title="Go to Login"
onPress={() => navigation.navigate('Login')}
/>
</View>
);
}
function RegisterationScreen({ navigation }) {
return (
<View >
<Registeration />
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
function LoginScreen({ navigation }) {
return (
<View >
<Login />
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Home' }}
/>
<Stack.Screen
name="Registeration"
component={RegisterationScreen}
options={{ title: 'Registeration' }}
/>
<Stack.Screen
name="Login"
component={LoginScreen}
options={{ title: 'Login' }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;

header in react navigation bottom tabs

Hi I am creating an app with react native and I am using react navigation for the menu but I find a problem and now when I create a menu with bottom tabs a header is also created and it gives me a problem for that reason I would like to know how I can solve it this or disappear the header
enter image description here
mi code is
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
function DetailsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details!</Text>
</View>
);
}
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
const HomeStack = createNativeStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
</HomeStack.Navigator>
);
}
const SettingsStack = createNativeStackNavigator();
function SettingsStackScreen() {
return (
<SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} />
<SettingsStack.Screen name="Details" component={DetailsScreen} />
</SettingsStack.Navigator>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
I would try adding an option to one of your screens to hide the header. Either the Tab.Screen(s) or one of the Stack's Screen(s) ─ it's up to you based on your use case.
For example:
...
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStackScreen} options={{headerShown: false}} />
<Tab.Screen name="Settings" component={SettingsStackScreen} options={{headerShown: false}} />
</Tab.Navigator>
</NavigationContainer>
);
}
This way you don't have two nested headers appearing at the same time.
React Navigation even recommends this from their docs when nesting navigators.
When nesting multiple stack, drawer or bottom tab navigator, headers from both child and parent navigators would be shown. However, usually it's more desirable to show the header in the child navigator and hide the header in the screen of the parent navigator.
To achieve this, you can hide the header in the screen containing the navigator using the headerShown: false option.
Reference: https://reactnavigation.org/docs/nesting-navigators/#nesting-multiple-navigators

Lost the back button React Native Navigation

I have a problem with react native navigation bar. At the third screen("Auth" at stack navigator) back button I lost back button. How can I fix it?
I use this function for the navigate:
this.props.navigation.navigate("Choose")
this.props.navigation.navigate("Auth")
Code of NavigationContainer:
<View style={styles.container}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Root" component={Hello} />
<Stack.Screen name="Choose" component={ChooseMessengers} />
<Stack.Screen name="Auth" component={Auth} />
</Stack.Navigator>
</NavigationContainer>
<StatusBar style="auto" />
</View>
To have the back button, you have to push screens on top of the stack.
this.props.navigation.push("Auth")

react-native-navigation: set custom header to all screen except one

I wanted to set a custom header to all screens inside a stack navigator except to particular a screen, because I wanted it to have the default header. I know that setting the header property of the options props of the navigator will do the trick to apply the custom header to all the screens, but my question is how to exclude one specific screen and just set it to default?
This is my current implementation for setting the custom header to all screens:
<Stack.Navigator
screenOptions={{
header: () => <CustomHeader />,
}}
>
<Stack.Screen name="Page1" component={Page1} />
<Stack.Screen name="Page2" component={Page2} />
<Stack.Screen name="Page3" component={Page3} />
</Stack.Navigator>
What can I further add to this code to exclude the application of custom header to Page3?
Try this.
<Stack.Navigator>
<Stack.Screen name="Page1" component={Page1} />
<Stack.Screen name="Page2" component={Page2} />
<Stack.Screen options={{ header: () => <CustomHeader /> }} name="Page3" component={Page3} />
</Stack.Navigator>
If anyone was wondering how to do the same for Drawer Navigator here is the solution that I have come up with:
import React, {Fragment} from 'react';
const NavHeader = props => {
// ... NavHeader code goes here
};
export const withHeader = Component => {
return props => {
return (
<Fragment>
<NavHeader {...props} />
<Component {...props} />
</Fragment>
);
};
};
Then in your Drawer you do:
<Drawer.Navigator>
<Drawer.Screen
name={ROUTES.DASHBOARD}
component={withHeader(DashboardContainer)} // <--- Wrap it around component here.
/>
</Drawer.Navigator>
If you want all screens except one to have custom header you wrap up every component with withHeader except one.
You can set Header for all screens. For anyone which you want to avoid you can set headerShown to false.
<NavigationContainer>
<Stack.Navigator
headerMode={'screen'}
screenOptions={{
header: ({navigation}) => <Header navigation={navigation} />,
}}> // This custom Nav Header is for all screen
<Stack.Screen
name="Home"
component={HomescreenTabs}
options={{headerShown: true}}// Will user Header component as Nav Header
/>
<Stack.Screen
name="Editor"
component={Editor}
options={{headerShown: false,}} // No Nav Header component will shown
/>
<Stack.Screen
name="SearchList"
component={SearchList}
options={{headerShown: true}} // Will user Header component as Nav Header
/>
</Stack.Navigator>
</NavigationContainer>

Categories

Resources