React Native Stack Navigation Screen Doesn't Exist - react-native

In App.js I have the following Stack Navigator:
<NavigationContainer>
<Stack.Navigator>
{user ? (
<Stack.Screen name="Home">
{(props) => <HomeScreen {...props} extraData={user} />}
</Stack.Screen>
) : (
<>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Registration" component={RegistrationScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</>
)}
</Stack.Navigator>
</NavigationContainer>
In the HomeScreen, I am trying to navigate to the "Profile" screen:
export default function HomeScreen(props) {
const onProfilePress = () => {
props.navigation.navigate('Profile')
};
return (
<View style={styles.container}>
<TouchableOpacity style={styles.button} onPress={onProfilePress}>
<Text style={styles.buttonText}>Profile</Text>
</TouchableOpacity>
</View>
);
}
However, I get a
The action 'NAVIGATE' with payload {"name":"Profile"} was not handled by any navigator.
Does anyone know how to fix?

Profile is only part of the stack when user is true.
Perhaps you meant to do something like this:
<NavigationContainer>
<Stack.Navigator>
{user ? (
<>
<Stack.Screen name="Home">
{(props) => <HomeScreen {...props} extraData={user} />}
</Stack.Screen>
<Stack.Screen name="Profile" component={ProfileScreen} />
</>
) : (
<>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Registration" component={RegistrationScreen} />
</>
)}
</Stack.Navigator>
</NavigationContainer>

Related

Hiding tab bar with nested navigation

I used nested navigation for my problem. Currently, however, the tab bar is only displayed on pages listed in TabNavigator. Is it possible to display on other pages as well? It is possible to display the tab bar also on screen5. I also have screen6 where I don't want to display the tab bar, so I solve it this way.
App.js
<NavigationContainer
ref={ref}
>
<Navigation />
</NavigationContainer>
Tab.js
const Tab = createBottomTabNavigator();
const Tabs = (props) => {
return(
<Tab.Navigator>
<Tab.Screen name="Screen1" component={Screen1} />
<Tab.Screen name="Screen2" component={Screen2} />
<Tab.Screen name="Screen3" component={Screen3} />
<Tab.Screen name="Screen4" component={Screen4} />
</Tab.Navigator>
);
}
<Stack.Navigator>
<Stack.Group screenOptions={{ headerShown: false }}>
<Stack.Screen name="Screen1" component={Tabs}/>
<Stack.Screen name="Screen2" component={Screen2}/>
<Stack.Screen name="Screen3" component={Screen3}/>
<Stack.Screen name="Screen4" component={Screen4}/>
<Stack.Screen name="Screen5" component={Screen5}/>
<Stack.Screen name="Screen6" component={Screen6}/>
</Stack.Group>
</Stack.Navigator>
Screen4
const Screen4 = ({navigation}) => {
return (
<SafeAreaView>
<Pressable onPress={() => {navigation.navigate('Screen5')}}>
<Text>Screen5</Text>
</Pressable>
</SafeAreaView>
);
}
export default Screen4;
I think you are aksing about this.
const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();
const HomeNavigator = () => {
<Stack.Navigator>
<Stack.Screen name="Screen1" component={Screen1} />
<Stack.Screen name="Screen2" component={Screen2} />
</Stack.Navigator>;
};
const ProfileNavigator = () => {
<Stack.Navigator>
<Stack.Screen name="Screen3" component={Screen3} />
<Stack.Screen name="Screen3" component={Screen3} />
</Stack.Navigator>;
};
const Tabs = (props) => {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeNavigator} />
<Tab.Screen name="Profile" component={ProfileNavigator} />
<Tab.Screen name="YourOtherNavigator" component={YourOtherNavigator} />
</Tab.Navigator>
);
};

Component not rendering in headerTitle

My HomeHeader component is not rendering within the headerTitle. I am expecting to render since when I do it as a direct string it shows up in the headerTitle.
const HomeHeader = (props) => {
return (
<View>
<Text>Home</Text>
</View>
)
}
function RootNavigator() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} options={{headerTitle: HomeHeader}} />
<Stack.Screen name="ChatRoom" component={ChatRoomScreen} options={{ headerShown: true }} />
<Stack.Screen name="NotFound" component={NotFoundScreen} options={{ title: 'Oops!' }} />
<Stack.Group screenOptions={{ presentation: 'modal' }}>
<Stack.Screen name="Modal" component={ModalScreen} />
</Stack.Group>
</Stack.Navigator>
);
}
Is there something I am missing? Please see the HomeHeader component up top and then it is currently within the headerTitle of my home screen.
I would add some size to the View and some style to the text maybe ...

Use DrawerNavigator and StackNavigator together [duplicate]

This is my tab navigator:
<Tab.Navigator initialRouteName="Home" backBehavior="initialRoute">
<Tab.Screen
name="Science"
component={Science}
options={{
tabBarLabel: 'Science',
tabBarIcon: ({color, size}) => (
<Image source={require('../../assets/images/science-tab.png')} />
),
}}
/>
<Tab.Screen name="Dashboard" component={Dashboard} />
</Tab.Navigator>
This is DrawerNavigator:
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
And this is my root navigator: Below Bottomnavigation is the tab navigator.
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="BottomNavigation"
component={BottomNavigation}
options={{title: this.createTitle()}}
/>
</Stack.Navigator>
</NavigationContainer>
I recommend you to make your TabNavigator a screen of DrawerNavigator
You can do something like this:
function TabNavigator({navigation}) {
return (
<Tab.Navigator>
// Your tab screens
</Tab.Navigator>
);
}
function DrawerNavigator() {
return (
<Drawer.Navigator>
<Drawer.Screen name="TabNavigator" component={TabNavigator} />
</Drawer.Navigator>
);
}
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="DrawerNavigator" component={DrawerNavigator} />
</Stack.Navigator>
</NavigationContainer>
);
};
If you want to open your drawer, you can call navigation.openDrawer() in your TabNavigator.
Update to address label issue
You can create a drawer content component to override the default behavior of adding the DrawerNavigator screens' labels as the content of the drawer.
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<DrawerItem
label="Home"
onPress={() => props.navigation.navigate('Home')}
/>
// ...
</DrawerContentScrollView>
);
}
Then you need to change the DrawerNavigator to this:
function DrawerNavigator({route}) {
return (
<Drawer.Navigator
drawerContent={(props) => <CustomDrawerContent {...props} />}>
<Drawer.Screen name="TabNavigator" component={TabNavigator} />
<Drawer.Screen name="Home" component={Home} />
</Drawer.Navigator>
);
}
So you can add new screens to your DrawerNavigator and navigate to them using the DrawerItem onPress function.
Of course make sure to import DrawerContentScrollView, DrawerItemList and DrawerItem from #react-navigation/drawer.
For more info look at: https://reactnavigation.org/docs/drawer-navigator/#providing-a-custom-drawercontent.

React Native Tab Navigator within Stack Navigator

I have the following Stack Navigator in App.js:
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Login" screenOptions={{headerShown:false}}>
{user ? (
<>
<Stack.Screen name="Home">
{(props) => <HomeScreen {...props} extraData={user} />}
</Stack.Screen>
<Stack.Screen name="Profile" component={ProfileScreen} />
<Stack.Screen name="Login" component={LoginScreen} />
</>
) : (
<>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Registration" component={RegistrationScreen} />
</>
)}
</Stack.Navigator>
</NavigationContainer>
);
I want to add a bottom tab navigator that shows up on the HomeScreen, and allows me to go back and forth between the HomeScreen and ProfileScreen. How can this be done?
The way to do this is to create a tab navigator component where Home and Profile are 2 screens of the navigator:
const Tab = createBottomTabNavigator();
function TabNavigator({route}) {
// Retrieve user from initalParams.
// The user is passed to initialParams in the snippet below.
const user = route.params?.user
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
);
}
Then the tab navigator can be a screen of your stack navigator:
return (
<NavigationContainer>
<Stack.Navigator
initialRouteName="Login"
screenOptions={{headerShown: false}}>
{user ? (
<>
<Stack.Screen name="Tabs" component={TabNavigator} initialParams={{user: user}}/>
</>
) : (
<>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Registration" component={RegistrationScreen} />
</>
)}
</Stack.Navigator>
</NavigationContainer>
);
If you need access to user from inside HomeScreen you can pass it using down using initialParams the same way it was passed down to the TabNavigator. If you don't want to keep passing stuff down like this you could try the Context api.
I removed the Login screen in the above example, because I assumed this was a mistake as you already have a Login screen defined for when you don't have an authenticated user.

ReactNative- Tab Navigator Inside Stack Navigator

Need to Show Tabs For Home Module after Signup Module
using React-navigation
Working Code with Only Stack Screens
const Stack = createStackNavigator();
const Bottom = createBottomTabNavigator();
render() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Welcome" headerMode='none' >
<Stack.Screen name="Welcome" component={WelcomeScreen}
options={{
title: '',
headerBackTitleVisible: false,
headerBackTitle: '',
headerShown: true
}}
/>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Signup" component={SignupScreen} />
<Stack.Screen name="ResetPassword" component={ResetPasswordScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Need to show Tab from SigninScreen Button
Tab 1: Dashboard:
Tab 2: Profile
Tried Code:
<Bottom.Navigator initialRouteName="Dashboard" >
<Bottom.Screen name="Dashboard" component={TabDashboard} />
<Bottom.Screen name="Profile" component={TabProfile} />
</Bottom.Navigator>
Now I need to combine these two block of codes so I can navigate to Tabs
Tab screen will have further navigations
The idea would be to wrap the tabs screen inside component and add it to the stack conditionally.
const HomeScreen = () =>{
return (
<Bottom.Navigator initialRouteName="Dashboard" >
<Bottom.Screen name="Dashboard" component={TabDashboard} />
<Bottom.Screen name="Profile" component={TabProfile} />
</Bottom.Navigator>
);
}
Your stack should change as below
render() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Welcome" headerMode='none' >
{
this.state.isSignedIn ? (
<>
<Stack.Screen name="Welcome" component={WelcomeScreen} />
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Signup" component={SignupScreen} />
<Stack.Screen name="ResetPassword" component={ResetPasswordScreen} />
</>
) : (
<>
<Stack.Screen name="ResetPassword" component={HomeScreen} />
</>
)
}
</Stack.Navigator>
</NavigationContainer>
);
}
IsSignedIn can be the state variable or a variable that you store the logged in status
You can refer the authentication flows
https://reactnavigation.org/docs/auth-flow