How do I handle a combination of stack and page navigation? - reactjs

I have a Bottom Tab Navigator that has two tabs. The Home tab contains a FlatList of objects. Once the user clicks on an object they should be routed to a page that contains the item that shouldn't show (as a tab) on the bottom tab, yet should show the bottom tab bar. My solution was to use a stack navigator in combination with a bottom tab navigator (shown below) as described in the official docs. However, when I nest the tab navigator inside of the stack navigator, it doesn't display the tab bar on the stack page. The other way around (stack navigator inside the tab navigator) I get an extra tab with the page, which is also an unwanted result.
I must be missing something. If anyone has a better way to route to an item in a list I'd like to hear it as well.
HomeStack (Stack Navigator) with the page Screen:
import { createStackNavigator } from "#react-navigation/stack";
import { ListItem } from "../components/ListItem/ListItem";
export default function StackNavigator() {
const Stack = createStackNavigator();
return (
<Stack.Navigator
screenOptions={{ headerShown: false }}
>
<Stack.Screen name="ListItem" component={ListItem} />
</Stack.Navigator>
);
}
TabsNavigator (BottomTabs) with HomeStack nested in side of it:
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import { Home } from "../screens/Home";
import { History } from "../screens/History";
import { FontAwesomeIcon } from "#fortawesome/react-native-fontawesome";
import { faList } from "#fortawesome/free-solid-svg-icons/faList";
import { faClockRotateLeft } from "#fortawesome/free-solid-svg-icons/faClockRotateLeft";
import HomeStack from "./HomeStack";
export default function TabsNavigator() {
const Tab = createBottomTabNavigator();
return (
<Tab.Navigator screenOptions={{ headerShown: false }}>
<Tab.Screen
name="List"
component={Home}
options={{
tabBarIcon: ({ focused }) => (
<FontAwesomeIcon
icon={faList}
style={{ color: focused ? "#317bc1" : "#CCC" }}
/>
),
}}
/>
<Tab.Screen
name="History"
component={History}
options={{
tabBarIcon: ({ focused }) => (
<FontAwesomeIcon
icon={faClockRotateLeft}
style={{ color: focused ? "#317bc1" : "#CCC" }}
/>
),
}}
/>
<Tab.Screen name="ListItem" component={HomeStack} />
</Tab.Navigator>
);
}
App:
import { StyleSheet, View } from "react-native";
import { Provider } from "react-redux";
import configureStore from "./src/redux";
import { NavigationContainer } from "#react-navigation/native";
import Navigator from "./src/routes/TabsNavigator";
export default function App() {
return (
<Provider store={configureStore()}>
<View style={{ flex: 1 }}>
<NavigationContainer>
<Navigator />
</NavigationContainer>
</View>
</Provider>
);
}

Take a reference from this code :
I've just now verified it, fine for me. Go through this code for proper understanding -
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function HomeScreen(props) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text onPress={() => props.navigation.navigate('NextScreen')}>Home!</Text>
</View>
);
}
function NextScreen(props) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text onPress={() => props.navigation.navigate('NextScreen2')}>Next!</Text>
</View>
);
}
function NextScreen2(props) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text onPress={() => props.navigation.navigate('NextScreen3')}>Next2!</Text>
</View>
);
}
function NextScreen3(props) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text onPress={() => props.navigation.navigate('HomeScreen')}>Next3!</Text>
</View>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
const stack = createNativeStackNavigator();
const StackNavigator = () => {
return <stack.Navigator option={{headerShown: false}}>
<stack.Screen name="HomeScreen" component={HomeScreen}/>
<stack.Screen name="NextScreen" component={NextScreen}/>
<stack.Screen name="NextScreen2" component={NextScreen2}/>
<stack.Screen name="NextScreen3" component={NextScreen3}/>
</stack.Navigator>
}
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={StackNavigator} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MyTabs />
</NavigationContainer>
);
}
As per your code change your HomeStack (Stack Navigator) likewise: -
import { createStackNavigator } from "#react-navigation/stack";
import { ListItem } from "../components/ListItem/ListItem";
import { Home } from '...<PATH TO HOME SCREEN>...';
const Stack = createStackNavigator();
export default function StackNavigator() {
return (
<Stack.Navigator
screenOptions={{ headerShown: false }}
>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="ListItem" component={ListItem} />
</Stack.Navigator>
);
}
Then change your first Tab likewise : -
<Tab.Screen
name="List"
component={HomeStack}
options={{
tabBarIcon: ({ focused }) => (
<FontAwesomeIcon
icon={faList}
style={{ color: focused ? "#317bc1" : "#CCC" }}
/>
),
}}
/>

Related

Payload not handled by any navigator in react navigation 6

I am updating my react-native app to use react navigation 6 and I'm trying to figure out how to connect to a screen.
The screen I'm trying to link/navigate to uses a bottomtabnavigator, and looks like this:
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
export const PatientScreen = () => {
const Tab = createBottomTabNavigator();
return (
<Tab.Navigator screenOptions={{ headerShown: false }} initialRouteName={'Visits'}>
<Tab.Screen name="Visits" component={VisitsTab}
options={{
tabBarLabel: 'Visits',
tabBarIcon: ({ color, size }) => (
<FontAwesome name="street-view" color={color} size={size} />
),
}}
/>
<Tab.Screen name="Chart" component={ChartTab}
options={{
tabBarLabel: 'Charts',
tabBarIcon: ({ color, size }) => (
<FontAwesome name="id-badge" color={color} size={size} />
),
}}
/>
<Tab.Screen name="Goals" component={GoalsTab}
options={{
tabBarLabel: 'Edit Goals',
tabBarIcon: ({ color, size }) => (
<FontAwesome name="trophy" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
);
}
I am trying to link to the above from within a screen that is part of a different navigator. That screen looks like this:
import { StyleSheet, Text, View, Tab, Button } from 'react-native';
import { PatientScreen } from './PatientScreen';
export const CaseloadScreen = ({navigation}) => {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Caseload</Text>
<Button title="Patient"
onPress={() => navigation.navigate('PatientScreen', { screen: 'Visits' })}
/>
</View>
);
}
When I click on the button above, I get this error:
The action 'NAVIGATE' with payload undefined was not handled by any navigator.
Do you have a screen named 'PatientScreen'?
So clearly I'm missing something, but it's unclear to me what that is. How do I make this PatientScreen which uses a bottomTabNavigator, linkable from the button link I listed above?
My navigator for the Caseload screen looks like this:
import React from 'react';
import { StyleSheet, View, Text, Button } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItemList,
DrawerItem,
} from '#react-navigation/drawer';
import { LoginScreen } from '../screens/LoginScreen';
import { CaseloadScreen } from '../screens/CaseloadScreen';
import { WeeklyScreen } from '../screens/WeeklyScreen';
import { ProfileScreen } from '../screens/ProfileScreen';
import { Ionicons, FontAwesome, MaterialCommunityIcons, AntDesign } from '#expo/vector-icons';
import { AvailablePatientScreen } from '../screens/AvailablePatientScreen';
const CustomDrawerContent = (props) => {
return (
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} style={{
activeTintColor: {
color: '#fff',
},
}} />
</DrawerContentScrollView>
);
}
const Drawer = createDrawerNavigator();
const DrawerNavigation = () => {
const icons = {
tintColor: '#fff',
size: 20,
}
return (
<Drawer.Navigator initialRouteName={'Caseload'}n
drawerContent={(props) => <CustomDrawerContent {...props} />}
screenOptions={{
labelStyle: {
color: '#fff',
},
inactiveTintColor: {
color: '#fff',
},
drawerStyle: {
backgroundColor: 'rgb(61,77,138)',
width: 240,
activeTintColor: 'rgb(61,77,138)',
activeBackgroundColor: '#fff',
inactiveTintColor: '#fff',
inactiveBackgroundColor: 'rgb(61,77,138)',
},
}}
>
<Drawer.Screen name="Caseload" component={CaseloadScreen} options={{
drawerIcon: () => (<Ionicons name="ios-home" size={icons.size} color={icons.tintColor} />)
}} />
<Drawer.Screen name="Weekly Summary" component={WeeklyScreen} options={{
drawerIcon: () => (<FontAwesome name="bar-chart" size={icons.size} color={icons.tintColor} />)
}} />
<Drawer.Screen name="Available RiverKids" component={AvailablePatientScreen} options={{
drawerIcon: () => (<FontAwesome name="child" size={icons.size} color={icons.tintColor} />)
}} />
<Drawer.Screen name="My Profile" component={ProfileScreen} options={{
drawerIcon: () => (<AntDesign name="profile" size={icons.size} color={icons.tintColor} />)
}} />
{/* <Drawer.Screen name="Patient" component={PatientScreen} options={{
drawerIcon: () => (<FontAwesome name="bar-chart" size={icons.size} color={icons.tintColor} />)
}} /> */}
<Drawer.Screen name="Login" component={LoginScreen} options={{ title: 'Sign Out',
drawerIcon: () => (<MaterialCommunityIcons name="logout" size={icons.size} color={icons.tintColor} />)
}} />
</Drawer.Navigator>
);
}
export const Navigator = () => {
return (
<NavigationContainer>
<DrawerNavigation />
</NavigationContainer>
);
}
In your drawer navigator there is no screen defined with the name 'PatientScreen';
I can see a commented screen in your drawer navigator which has a name Patient and the component is PatientScreen. If you wish to navigate the Patient Screen from the drawer, do uncomment that code and then do the below
import { StyleSheet, Text, View, Tab, Button } from 'react-native';
export const CaseloadScreen = ({navigation}) => {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Caseload</Text>
<Button title="Patient"
onPress={() => navigation.navigate('Patient', { screen: 'Visits' })}
/>
</View>
);
}
Or else if you wish to navigate the PatientScreen only from the Caseload Screen, then create a Stack Navigator with the caseload and patient screen and then in the drawer navigator use that stack navigator in place of caseload screen

React Navigation. How to navigate with class component?

I am trying to navigate with React Navigate.
When clicking on the image I get this error in console:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
I have tried different methods to navigate, but without success. Any suggestions?
This is my code:
import React, { Component } from 'react';
import { StyleSheet, Text, View, SafeAreaView, Image, TouchableHighlight } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { useNavigation } from '#react-navigation/native';
const Stack = createNativeStackNavigator();
import Home from './screens/homeScreen';
import Teams from './screens/teamsScreen';
export default class App extends Component {
GoTo({ screenName }) {
const navigation = useNavigation();
navigation.navigate(screenName);
}
render() {
return (
<SafeAreaView style={{flex: 1,}}>
<View style={styles.header}>
<TouchableHighlight onPress={() => this.GoTo('Teams')}>
<Image
style={styles.headerLogo}
source={{uri: 'https://yukigassen.no/uploads/Yukigassen_Logo_Big_Transparent.png'}}
resizeMode={'stretch'}
/>
</TouchableHighlight>
<View style={styles.headerRight}>
<Image
style={{width: 25, height: 25}}
source={{uri: 'https://icons.iconarchive.com/icons/dtafalonso/android-lollipop/512/Settings-icon.png'}}
/>
</View>
</View>
<View style={styles.screen}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} options={{headerShown: false}} />
<Stack.Screen name="Teams" component={Teams} options={{headerShown: false}} />
</Stack.Navigator>
</NavigationContainer>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
header: {
height: '7.5%',
padding: 5,
},
headerLogo: {
width: 160,
height: 50,
marginLeft: 10,
},
headerRight:{
position: 'absolute',
right: 5,
top: 15,
},
screen: {
flex: 1,
},
});
useNavigation() is a hook that cannot be used with class components but there is a way around it. You can create a wrapper component and pass the navigation prop into your class component.
class App extends Component {
render() {
// Get it from props
const { navigation } = this.props;
...
}
}
// Wrap and export
export default function(props) {
const navigation = useNavigation();
return <App {...props} navigation={navigation} />;
}
Example from https://reactnavigation.org/docs/use-navigation/
you can try this approach, make that comp default route and check, lemme know if this helps :) thanks
import React, { Component } from 'react';
import { StyleSheet, Text, View, SafeAreaView, Image, TouchableHighlight } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { useNavigation } from '#react-navigation/native';
const Stack = createNativeStackNavigator();
import Home from './screens/homeScreen';
import Teams from './screens/teamsScreen';
const DefaultRoute = () => {
GoTo({ screenName }) {
const navigation = useNavigation();
navigation.navigate(screenName);
}
return(
<SafeAreaView style={{flex: 1,}}>
<View style={styles.header}>
<TouchableHighlight onPress={() => this.GoTo('Teams')}>
<Image
style={styles.headerLogo}
source={{uri: 'https://yukigassen.no/uploads/Yukigassen_Logo_Big_Transparent.png'}}
resizeMode={'stretch'}
/>
</TouchableHighlight>
<View style={styles.headerRight}>
<Image
style={{width: 25, height: 25}}
source={{uri: 'https://icons.iconarchive.com/icons/dtafalonso/android-lollipop/512/Settings-icon.png'}}
/>
</View>
</View>
</SafeAreaView>
)
}
export default class App extends Component {
render() {
return (
<SafeAreaView style={styles.screen}>
<NavigationContainer>
<Stack.Navigator initialRouteName="DefaultRoute">
<Stack.Screen name="DefaultRoute" component={DefaultRoute} options={{headerShown: false}} />
<Stack.Screen name="Home" component={Home} options={{headerShown: false}} />
<Stack.Screen name="Teams" component={Teams} options={{headerShown: false}} />
</Stack.Navigator>
</NavigationContainer>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
header: {
height: '7.5%',
padding: 5,
},
headerLogo: {
width: 160,
height: 50,
marginLeft: 10,
},
headerRight:{
position: 'absolute',
right: 5,
top: 15,
},
screen: {
flex: 1,
},
});

need to display the header in all screen on react native navigation V5

i have the following header.js
import React from 'react';
import {View, Text, StyleSheet, Image} from 'react-native';
import {MaterialCommunityIcons} from '#expo/vector-icons';
export default function header({navigation}, title) {
const openMenu =() => {
navigation.openDrawer()
}
return (
<View style={styles.header}>
<MaterialCommunityIcons name='menu'
size={24} color='black'
onPress={openMenu}
style={styles.icon}
/>
<View style={styles.headerTitle}>
<Image style={styles.logo} source={require('../assets/oau-ico-hat.png')}/>
<Text style={styles.headerText}>title={title}</Text>
{/* */}
</View>
</View>
)
}
const styles = StyleSheet.create({
header:{
width:'100%',
height: '100%',
flexDirection:'row',
alignItems:'center',
justifyContent:'center',
},
headerText:{
fontWeight: 'bold',
fontSize: 20,
color: '#333',
letterSpacing: 1,
marginTop:8,
marginHorizontal: 50,
marginLeft:10,
},
logo: {
width: 40,
height: 40,
},
icon:{
position:'absolute',
left: 0.7,
},
headerTitle:{
flexDirection:'row',
},
})
then i had the following App.js
const Drawer = createDrawerNavigator();
const DrawerNavigator=() => {
return (
<Drawer.Navigator
drawerContent={props => <DrawerContent {...props}
/>}
>
<Drawer.Screen name="Home" component={StackNavigator}
/>
<Drawer.Screen name="Faculties" component={Faculty}
/>
</Drawer.Navigator>
)
}
const Tab = createBottomTabNavigator();
const TabNavigator = ({navigation}) => (
<Tab.Navigator
screenOptions={{
headerStyle:{backgroundColor: "tomato" , elevation:0},
headerTintColor:"#fff",
headerTitleAlign:'center',
headerTitle: () => <Header navigation={navigation} title='O.A.U'/>
}}>
<Tab.Screen name="Home" component={DrawerNavigator} />
<Tab.Screen name="Faculties" component={Faculty}
/>
</Tab.Navigator>
)
const Stack = createStackNavigator();
const StackNavigator = ({navigation}) => (
<Stack.Navigator
screenOptions={{
headerStyle:{backgroundColor: "tomato" , elevation:0},
headerTintColor:"#fff",
headerTitleAlign:'center',
headerTitle: () => <Header navigation={navigation} title='O.A.U'/>
}}
>
<Stack.Screen name="Home" component={Home}
options={() => {<Header navigation={navigation} title='O.A.U'/>}}
/>
<Stack.Screen name="TabsBottom" component={Faculty}
/>
</Stack.Navigator>
);
const styles = StyleSheet.create({
header:{
alignItems:'center',
},
})
export default function App() {
return (
<NavigationContainer>
<TabNavigator/>
</NavigationContainer>
);
}
I have homeStack.js where in React Navigation V4 it was working as follow:any idea how can i make that work in V% react-navigation
import React from 'react';
import {createStackNavigator} from '#react-navigation/stack';
import Header from '../shared/header';
import Home from '../screens/homeScreen';
import Faculty from '../screens/faculties'
const screens ={
Home: {
screen: Home,
screenOptions:({ navigation } )=> {
return {
headerTitle: () => <Header navigation={navigation} title='O.A.U'/>,
}
}
},
Faculty: {
screen: Faculty,
navigatioptions:({ navigation } )=> {
return {
headerTitle: () => <Header navigation={navigation} title='O.A.U'/>,
}
}
}
}
const HomeStack = createStackNavigator();
export default HomeStack;
i have a drwer.js for the drawer meny as follow:
import React from "react";
import { StyleSheet, View } from "react-native";
import {
DrawerContentScrollView,
DrawerItem,
DrawerItemList,
} from "#react-navigation/drawer";
import {
Avatar,
Title,
Caption,
Paragraph,
Drawer,
Text,
TouchableRipple,
Switch,
} from "react-native-paper";
import { MaterialCommunityIcons, FontAwesome5 } from "#expo/vector-icons";
import Home from './homeStack'
export function DrawerContent({ ...props }) {
return (
<View style={{ flex: 1 }}>
<DrawerContentScrollView {...props}>
{/* <DrawerItemList {...props}/> */}
<DrawerItem
icon={({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
)}
label="Home"
onPress={() => props.navigation.navigate("Home")}
/>
<DrawerItem
icon={({ color, size }) => (
<FontAwesome5 name="university" color={color} size={size} />
)}
label="Faculties"
onPress={() => props.navigation.navigate("Faculties")}
/>
</DrawerContentScrollView>
</View>
);
}
my questions as follow:
1.how can i display the header in all screen as the header will include the menu burger that pulls the drawer menu?
2. when clicking on Faculties menu from tab the drawer menu is not working unless i click on home menu from tab navigation, is my nested navigation correct or where am I going wrong?
P/S: please note this my first time on developing mobile app using react.
you can have a look at github and see if you can help from there # https://github.com/sudani/Uni_app.git
after spending the last 2 days looking for answer i found great youtube tutorial, i frogot about rules posting link but here what i have managed to do:
removed all the stack screens, tab screens to separate file then import the file into App.js:
the file as follow:
import React from 'react';
import {createStackNavigator} from '#react-navigation/stack';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
import Icon from 'react-native-vector-icons/Ionicons';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import HomeScreen from './homeScreen'
import FacultyScreen from './faculties';
const HomeStack = createStackNavigator();
const FacultyStack = createStackNavigator();
const Tab = createMaterialBottomTabNavigator();
const MainTabScreen =() => (
<Tab.Navigator
initialRouteName="Home"
activeColor="#fff"
barStyle={{ backgroundColor: 'tomato' }}
>
<Tab.Screen
name="Home"
component={HomeStackScreen}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="home" color={color} size={26} />
),
}}
/>
<Tab.Screen
name="Faculty"
component={FacultyStackScreen}
options={{
tabBarLabel: 'Updates',
tabBarIcon: ({ color }) => (
<MaterialCommunityIcons name="bell" color={color} size={26} />
),
}}
/>
</Tab.Navigator>
)
export default MainTabScreen;
const HomeStackScreen =({navigation}) => (
<HomeStack.Navigator
screenOptions={{
headerStyle: { backgroundColor: "tomato", elevation: 0 },
headerTintColor: "#fff",
headerTitleAlign: "center",
headerShown:true,
}}
>
<HomeStack.Screen name= "Home" component={HomeScreen}
options={{
title:'Overview',
headerLeft: () => (
<Icon.Button name="ios-menu" size={26}
backgroundColor="tomato" onPress={() => navigation.openDrawer() }></Icon.Button>
)
}}
/>
</HomeStack.Navigator>
)
const FacultyStackScreen =({navigation}) => (
<FacultyStack.Navigator
screenOptions={{
headerStyle: { backgroundColor: "tomato", elevation: 0 },
headerTintColor: "#fff",
headerTitleAlign: "center",
headerShown:true,
}}
>
<FacultyStack.Screen name= "Faculty" component={FacultyScreen}
options={{
headerLeft: () => (
<Icon.Button name="ios-menu" size={26}
backgroundColor="tomato" onPress={() => navigation.openDrawer() }></Icon.Button>
)
}}
/>
</FacultyStack.Navigator>
)
then the App.js as follow:
import React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createDrawerNavigator} from '#react-navigation/drawer';
import MainTabScreen from './app/screens/MaintabScreen';
import { DrawerContent } from "./app/routes/drawer";
const Drawer = createDrawerNavigator();
export default function App() {
return (
<NavigationContainer initialRouteName= "Home">
<Drawer.Navigator drawerContent={(props) => <DrawerContent {...props} />}>
<Drawer.Screen name="Home" component={MainTabScreen}/>
{/* <Drawer.Screen name="Faculty" component={FacultyStackScreen}/> */}
</Drawer.Navigator>
</NavigationContainer>
);
}
the drawer helper stayed the same as before
import React from "react";
import { StyleSheet, View } from "react-native";
import {
DrawerContentScrollView,
DrawerItem,
DrawerItemList,
} from "#react-navigation/drawer";
import {
Avatar,
Title,
Caption,
Paragraph,
Drawer,
Text,
TouchableRipple,
Switch,
} from "react-native-paper";
import { MaterialCommunityIcons, FontAwesome5 } from "#expo/vector-icons";
import Home from './homeStack'
export function DrawerContent({ ...props }) {
return (
<View style={{ flex: 1 }}>
<DrawerContentScrollView {...props}>
{/* <DrawerItemList {...props}/> */}
<DrawerItem
icon={({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
)}
label="Home"
onPress={() => props.navigation.navigate("Home")}
/>
<DrawerItem
icon={({ color, size }) => (
<FontAwesome5 name="university" color={color} size={size} />
)}
label="Faculties"
onPress={() => props.navigation.navigate("Faculty")}
/>
</DrawerContentScrollView>
</View>
);
}
I found this an Easy way of managing the nested navigation and it is almost what i wanted if anyone has better improvement suggestion that will be great

React Native Stack Navigator Use State

I try to make Share State Data From MyStack Component.
Components of Second Data is Always changed But First Screen is not
Could you tell me about what is problem of this??
And What do i have to Change.
thank you :D
import React ,{ useState } from 'react';
import { Button, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
function First({route , navigation}) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title={route.params.count.toString()}
onPress={() => navigation.navigate('Second')}/>
</View>
);
}
function Second({route , navigation }) {
route.params.setCount(route.params.count + 1);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title={route.params.count.toString()}
onPress={() => { navigation.goBack()}}
/>
</View>
);
}
const Stack = createStackNavigator();
function MyStack() {
const [count, setCount] = useState(0);
return (
<Stack.Navigator>
<Stack.Screen name="First" component={First} initialParams={{ count: count , setCount : setCount }}/>
<Stack.Screen name="Second" component={Second} initialParams={{ count: count ,setCount : setCount}}/>
</Stack.Navigator>
);
}
export default function App(props) {
return (
<NavigationContainer>
<MyStack props={props}/>
</NavigationContainer>
);
}
The reason for the above not working is the FirstScreen is not being re rendered. You cant dynamically change the intialparams after the screen is rendered.
Even your screen 2 is not working properly, you set it but you see the updated value when you revisit the screen.
The way to fix this is to use the context api which you can use to skip the navigation params.
And always use a hook like useEffect or a buttonclick to update the context otherwise it would keep rerendering which would result in an error.
The code would be like below.
import React, { useState, createContext, useContext } from 'react';
import { Button, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const appContext = createContext();
function First({ route, navigation }) {
const context = useContext(appContext);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title={context.count.toString()}
onPress={() => navigation.navigate('Second')}
/>
</View>
);
}
function Second({ route, navigation }) {
const context = useContext(appContext);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title={context.count.toString()}
onPress={() => {
navigation.goBack();
}}
/>
<Button
title="Add to Count"
onPress={() => {
context.setCount(context.count + 1);
}}
/>
</View>
);
}
const Stack = createStackNavigator();
function MyStack() {
const [count, setCount] = useState(0);
const state = { count, setCount };
return (
<appContext.Provider value={state}>
<Stack.Navigator>
<Stack.Screen name="First" component={First} />
<Stack.Screen name="Second" component={Second} />
</Stack.Navigator>
</appContext.Provider>
);
}
export default function App(props) {
return (
<NavigationContainer>
<MyStack props={props} />
</NavigationContainer>
);
}

React navigator not showing two route or all route

** I wanna to use react navigator on my app. Here I try to making two route and i want to see these. But i only see first route component. Theirs no button about 'def'. But copy those code from react navigator. i also found in snack emulator there also showing one route. does my code is wrong?? Advance thanks **
import { StatusBar } from 'expo-status-bar';
import React,{useState} from 'react';
import { StyleSheet, Text, View } from 'react-native';
import MultipleDateEntrys from './UI/Pages/MultipleDateEntrys.js'
import MaxCountrysEntry from './UI/Pages/MaxCountryData'
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const Stack = createStackNavigator();
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>abc</Text>
</View>
);
}
function def() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>cde</Text>
</View>
);
}
export default function App() {
const title = useState('Corona Highlight')
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Overview' }}/>
<Stack.Screen
name="Mon"
component={def}
options={{ title: 'def' }}/>
</Stack.Navigator>
{/* <Text style={styles.title}>{title}</Text> */}
</NavigationContainer>
);
}
When using a stack navigator only one screen would be shown which is the intended behavior.
You will have to navigate to the other screen using a button or some similar component.
All screens get a navigation prop you can use it to navigate.
In order to navigate to a screen you have to use the navigation.navigate("ScreenName"). Here the screen name would be the name that you provide in the stack when you initialize.
function HomeScreen({navigation}) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button title="Navigate" onPress={()=>navigation.navigate("Mon")}/>
<Text>abc</Text>
</View>
);
}
If you want both the screen in the same view you can use a tab navigator, which would allow you to switch screen using a tab
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home"
component={HomeScreen}
options={{ title: 'Overview' }} />
<Tab.Screen name="Mon"
component={def}
options={{ title: 'def' }}/>
</Tab.Navigator>
);
}

Resources