How to create a Drawer navigation in react native - react-native

I am trying to create a Stack navigation, A Drawer navigation and a Bottom Tab navigation. My Stack navigation and Bottom Tab navigation is working fine, but Can't make the Drawer Navigation. Could you tell me what I am missing here? It seems to me Drawer navigation and Tab navigation has a conflict in my code...but can't find why ??? Please help.
My App.js
import 'react-native-gesture-handler';
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator, DrawerContentScrollView,DrawerItemList,DrawerItem, } from '#react-navigation/drawer';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import HomeScreen from './src/screens/HomeScreen';
import FeedScreen from './src/screens/FeedScreen';
import Cards from './src/screens/CardScreen';
import ProfileScreen from './src/screens/ProfileScreen';
import Message from './src/screens/MessagesScreen';
function DetailsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details!</Text>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to Cards"
onPress={() => navigation.navigate('Cards')}
/>
</View>
);
}
const HomeStack = createNativeStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator initialRouteName="Home">
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="FeedScreen" component={FeedScreen} />
<HomeStack.Screen name="Message" component={Message} />
</HomeStack.Navigator>
);
}
const SettingsStack = createNativeStackNavigator();
function SettingsStackScreen() {
return (
<SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} />
<SettingsStack.Screen name="Cards" component={Cards} />
</SettingsStack.Navigator>
);
}
const ProfileStack = createNativeStackNavigator();
function ProfileStackScreen(){
return (
<ProfileStack.Navigator>
<ProfileStack.Screen name="Profile" component={ProfileScreen}/>
{/* <ProfileStack.Screen name="Cards" component={Cards}/> */}
</ProfileStack.Navigator>
)
}
const Drawer = createDrawerNavigator();
function MyDrawer() {
return (
<Drawer.Navigator screenOptions={{ drawerPosition: 'left' }}>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Message" component={Message} />
</Drawer.Navigator>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator screenOptions={{ headerShown: false }}>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsStackScreen} />
<Tab.Screen name="Profile" component={ProfileStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}

I Have found the solutions, I just entered tab navigation into drawer navigation and now it's working fine
import 'react-native-gesture-handler';
import Animated, {
useSharedValue,
withTiming,
useAnimatedStyle,
Easing,
} from 'react-native-reanimated';
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator, DrawerContentScrollView,
DrawerItemList,
DrawerItem, } from '#react-navigation/drawer';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import HomeScreen from './src/screens/HomeScreen';
import FeedScreen from './src/screens/FeedScreen';
import Cards from './src/screens/CardScreen';
import ProfileScreen from './src/screens/ProfileScreen';
import Message from './src/screens/MessagesScreen';
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
const Drawer = createDrawerNavigator();
function Tabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} options={{ headerShown: false }} />
<Tab.Screen name="Profile" component={ProfileScreen} options={{ headerShown: false }} />
<Tab.Screen name="Message" component={Message} options={{ headerShown: false }} />
</Tab.Navigator>
);
}
function StackNavigator() {
return (
<Stack.Navigator>
<Stack.Screen name="HomeScreen" component={HomeScreen} options={{ headerShown: false }} />
<Stack.Screen name="Message" component={Message} />
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Stack">
<Drawer.Screen name="Tabs" component={Tabs} />
</Drawer.Navigator>
</NavigationContainer>
);
}

Related

Tab Navigation Not Showing

I define my stacknavigation like this
/* eslint-disable prettier/prettier */
import React, {useState} from 'react';
import YourApp from './TabNavigation';
import {createStackNavigator} from '#react-navigation/stack';
import TopTabNavigation from './TopTabNavigation';
const Stack = createStackNavigator();
export default function MyStack() {
const [isShowNavbar, setIsShowNavbar] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
return (
<Stack.Navigator>
<Stack.Screen
name="PilihPasar"
component={PilihPasar}
options={{
title: '',
headerTintColor: '#fff',
headerTitleStyle: {
fontFamily: 'sans-serif-medium',
fontSize: 20,
},
}}
/>
<Stack.Screen
name="Home"
component={Home}
options={{headerShown: false}}
/>
<Stack.Screen
name="All Navigation"
component={YourApp}
options={{headerShown: false}}
/>
in new screen i create this
`
<View>
<TouchableOpacity
style={styles.linearGradient}
onPress={() => {
console.log("Testing");
this.props.navigation.navigate('Home');
}}>
<LinearButton text="Masuk" />
</TouchableOpacity>
</View>
`
The tab navigation not showing because i make home screen in stack navigation, and i create a new screen before home screen. So, i must make home screen in stack navigation so that the two pages are connected to each other.

React-native bottom navigation with stacknavigator

I'm new to React Native and trying to learn. but I couldn't do what I wanted to do.
I have Tab Navigations and I want to Open Stack when I click the button. But I can't figure out how to do it, thanks in advance for your help.
Snack
import * as React from 'react';
import { View,Text,TouchableOpacity,Button } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator();
function Home() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Page</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('FeedScreen')}
/>
</View>
);
}
function FeedScreen() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Details} />
</Stack.Navigator>
);
}
function Details() {
return <View><Text>Details</Text></View>;
}
function Profile() {
return <View>
<Text>Profile</Text>
</View>;
}
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Profile" component={Profile} />
</Tab.Navigator>
</NavigationContainer>
);
}
Your tabs can take a StackNavigator as the component and by default it will go to the first screen in that stack when you press the tab.
edit to your code
import * as React from 'react';
import { View,Text,TouchableOpacity,Button } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator();
function Home() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Page</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('FeedScreen')}
/>
</View>
);
}
function Details() {
return <View><Text>Details</Text></View>;
}
function Profile() {
return <View>
<Text>Profile</Text>
</View>;
}
function FeedScreen() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Details" component={Details} />
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Feed" component={FeedScreen} />
<Tab.Screen name="Profile" component={Profile} />
</Tab.Navigator>
</NavigationContainer>
);
}
The navigation.navigate(...) part becomes a little more complicated but not too bad. See the example here. This one is basically opposite of your setup where the tabs are nested within a stack navigator.

React drawer Navigation lags while opening

I am nesting a drawer navigation on top of a stack navigator. It works, but the problem is that it lags excessively while opening the drawer. What could be the issue here?
import React, { useEffect, useState } from "react";
import CartIcon from "../CartIcon";
import Home from "../../screens/Home";
import Orders from "../../screens/Orders";
import ProductsScreen from "../../screens/ProductsScreen";
import Cart from "../../screens/Cart";
import { createNativeStackNavigator } from "#react-navigation/native-stack";
import HomeHeader from "../HomeHeader";
import OrdersDetails from "../../screens/OrdersDetails";
import { createDrawerNavigator } from "#react-navigation/drawer";
const Drawer = createDrawerNavigator()
const Stack = createNativeStackNavigator();
My drawer navigator here
const HomeScreen=()=> {
return (
<Drawer.Navigator>
<Drawer.Screen name="Home" component={Home} options={() => ({
title: "BarPoint",
headerRight: () => <HomeHeader />,
})} />
</Drawer.Navigator>
);
}
stack navigator here
const AppStack = () => {
return (
<Stack.Navigator>
<Stack.Screen
name="HomeScreen"
component={HomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="ProductsScreen"
component={ProductsScreen}
options={({ navigation }) => ({
title: "Products",
headerRight: () => <CartIcon navigation={navigation} />,
})}
/>
<Stack.Screen name="Cart" component={Cart} />
<Stack.Screen name="Orders" component={Orders} />
<Stack.Screen name="OrdersDetails" component={OrdersDetails} />
</Stack.Navigator>
);
};
export default AppStack;
Add useLegacyImplementation in Drawer.Navigator and compile.
const HomeScreen=()=> {
return (
<Drawer.Navigator
useLegacyImplementation //<- Add here
>
<Drawer.Screen name="Home" component={Home} options={() => ({
title: "BarPoint",
headerRight: () => <HomeHeader />,
})} />
</Drawer.Navigator>
);
}
It occurred an Error to me by adding useLegacyImplementation.
Here is my code.Also,I can't touch off my sidebar by navigation.openDrawer
my devices: xcode13 react-navigation6.x
import React ,{Component}from 'react';
import { Button, View ,Text,StyleSheet} from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
const Drawer=createDrawerNavigator()
//two function
function HomeScreen(prop){
return(
<View style={styles.container}>
<Text style={styles.text}>Home Screen</Text>
<Button title={"Open Drawer"} onPress={()=>prop.navigation.openDrawer()}/>
<Button title={"Toggle Drawer"} onPress={()=>prop.navigation.toggleDrawer()}/>
</View>
)
}
function NewsScreen(prop){
return(
<View style={styles.container}>
<Text style={styles.text}>News Screen</Text>
<Button title={"jump to Home"} onPress={()=>prop.navigation.navigate('Home')}/>
</View>
)
}
export default class index extends Component{
render(){
return(
<Drawer.Navigator useLegacyImplementation={true} >
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="News" component={NewsScreen} />
</Drawer.Navigator>
)
}
}
const styles=StyleSheet.create({
container:{
flex:1,
justifyContent:'center',
alignItems: 'center',
},
text:{
fontSize:40
}
})

Combining a stack navigator with a drawer navigator in react native

So I'm new to react native and react navigation.
I'm building an app that will have 7 main screens:
HomeScreen, ProfileScreen, CocktailDetailScreen and PublishRecipeScreen (which I want to be able to access through a drawer navigator).
LandingScreen, LoginScreen and RegisterScreen (which I don't want to show in the drawer navigator. I just want to show the LandingScreen when the user isn't logged in, and either of the other if the user want's to log in or register).
I've been able to put up a stack navigator that works fine, but I don't understand how to combine this with the drawer navigator I want. I've tried different approaches but I get errors like:
The action 'OPEN_DRAWER' was not handled by any navigator.
Is your screen inside a Drawer navigator?
or
Uncaught Error: Looks like you have nested a 'NavigationContainer' inside another. Normally you need only one container at the root of the app, so this was probably an error. If this was intentional, pass 'independent={true}' explicitly. Note that this will make the child navigators disconnected from the parent and you won't be able to navigate between them.
This is my code so far.
App.tsx
import { SafeAreaProvider } from 'react-native-safe-area-context'
import useCachedResources from './hooks/useCachedResources'
import Navigation from './navigation'
export default function App() {
const isLoadingComplete = useCachedResources()
if (!isLoadingComplete) {
return null
} else {
return (
<SafeAreaProvider>
<Navigation />
</SafeAreaProvider>
)
}
}
(navigation) index.tsx
import { NavigationContainer } from '#react-navigation/native'
import { createNativeStackNavigator } from '#react-navigation/native-stack'
import * as React from 'react'
import LandingScreen from '../screens/LandingScreen'
import LoginScreen from '../screens/LoginScreen'
import RegisterScreen from '../screens/RegisterScreen'
import HomeScreen from '../screens/HomeScreen'
import ProfileScreen from '../screens/ProfileScreen'
import CocktailDetailScreen from '../screens/CocktailDetailScreen'
import PublishRecipeScreen from '../screens/PublishRecipeScreen'
import Header from '../components/Header'
import DrawerNavigator from '../components/DrawerNavigator'
import { RootStackParamList } from '../types'
export default function Navigation() {
const Stack = createNativeStackNavigator<RootStackParamList>()
return (
<NavigationContainer>
<Stack.Navigator >
<Stack.Screen name='LandingScreen' component={LandingScreen} options={{headerShown: false}} />
<Stack.Screen name='LoginScreen' component={LoginScreen} options={{headerShown: false}} />
<Stack.Screen name='RegisterScreen' component={RegisterScreen} options={{headerShown: false}} />
<Stack.Screen name='HomeScreen' component={HomeScreen} options={{ header: () => <Header/> }} />
<Stack.Screen name='ProfileScreen' component={ProfileScreen} options={{ header: () => <Header/> }} />
<Stack.Screen name='CocktailDetailScreen' component={CocktailDetailScreen} options={{ header: () => <Header/> }} />
<Stack.Screen name='PublishRecipeScreen' component={PublishRecipeScreen} options={{ header: () => <Header/> }} />
</Stack.Navigator>
</NavigationContainer>
)
}
header.tsx
import React from 'react'
import { useNavigation } from '#react-navigation/native'
import { useDrawerStatus } from '#react-navigation/drawer'
import { DrawerActions } from '#react-navigation/native'
import { StyleSheet, Text, View } from 'react-native'
import { AntDesign } from '#expo/vector-icons'
const Header = () => {
const navigation = useNavigation()
return (
<View style={styles.container}>
<Text style={styles.title} onPress={() => navigation.navigate('RegisterScreen')}>Mixr</Text>
<View style={styles.iconContainer} >
<AntDesign name='user' style={styles.icon} size={30} color='white' onPress={() => navigation.dispatch(DrawerActions.openDrawer())} />
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
backgroundColor: '#E51C27',
alignSelf: 'stretch'
},
title: {
fontSize: 40,
fontWeight: 'bold',
marginTop: 6,
marginBottom: 6,
marginLeft: 10
},
iconContainer: {
backgroundColor: 'black',
borderBottomLeftRadius: 50,
borderBottomRightRadius: 50,
borderTopLeftRadius: 50,
borderTopRightRadius: 50,
marginRight: 10
},
icon: {
padding: 5
}
})
export default Header
DrawerNavigator.tsx
import React from 'react'
import { createDrawerNavigator, useDrawerStatus } from '#react-navigation/drawer'
import { NavigationContainer } from '#react-navigation/native'
import HomeScreen from '../screens/HomeScreen'
import ProfileScreen from '../screens/ProfileScreen'
import CocktailDetailScreen from '../screens/CocktailDetailScreen'
import PublishRecipeScreen from '../screens/PublishRecipeScreen'
const DrawerNavigator = () => {
const Drawer = createDrawerNavigator()
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name='HomeScreen' component={HomeScreen} />
<Drawer.Screen name='ProfileScreen' component={ProfileScreen} />
<Drawer.Screen name='CocktailDetailScreen' component={CocktailDetailScreen} />
<Drawer.Screen name='PublishRecipeScreen' component={PublishRecipeScreen} />
</Drawer.Navigator>
</NavigationContainer>
)
}
export default DrawerNavigator
I want to show a header in all of this pages (HomeScreen, ProfileScreen, CocktailDetailScreen and PublishRecipeScreen) and from that header be able to open/close the drawer. I don't quite understand how to link the stack navigator with the drawer.
From a more theoretical point of view, I don't really understand the difference between the stack navigator, the drawer, and other options like tab or bottom navigators.
I mean, besides that the drawer navigator shows in a drawer and the bottom one shows at the bottom. Is there a conceptual difference between them?
Full code can be found here: https://github.com/coccagerman/mixr
I think I figured it out.
What I did is nest the drawer navigator within the stack navigator.
To do so, I passed the Drawer navigator as the component of each of the screens I wanted it to be in.
Like so:
(navigation) index.tsx
import { NavigationContainer } from '#react-navigation/native'
import { createNativeStackNavigator } from '#react-navigation/native-stack'
import * as React from 'react'
import LandingScreen from '../screens/LandingScreen'
import LoginScreen from '../screens/LoginScreen'
import RegisterScreen from '../screens/RegisterScreen'
import Header from '../components/Header'
import DrawerNavigator from '../components/DrawerNavigator'
import { RootStackParamList } from '../types'
export default function Navigation() {
const Stack = createNativeStackNavigator<RootStackParamList>()
return (
<NavigationContainer>
<Stack.Navigator >
<Stack.Screen name='LandingScreen' component={LandingScreen} options={{headerShown: false}} />
<Stack.Screen name='LoginScreen' component={LoginScreen} options={{headerShown: false}} />
<Stack.Screen name='RegisterScreen' component={RegisterScreen} options={{headerShown: false}} />
<Stack.Screen name='HomeScreen' component={DrawerNavigator} options={{ header: () => <Header/> }} />
<Stack.Screen name='ProfileScreen' component={DrawerNavigator} options={{ header: () => <Header/> }} />
<Stack.Screen name='CocktailDetailScreen' component={DrawerNavigator} options={{ header: () => <Header/> }} />
<Stack.Screen name='PublishRecipeScreen' component={DrawerNavigator} options={{ header: () => <Header/> }} />
</Stack.Navigator>
</NavigationContainer>
)
}
And in the drawer navigator I assign the corresponding screen component to each screen:
DrawerNavigator.tsx
import React from 'react'
import { createDrawerNavigator } from '#react-navigation/drawer'
import HomeScreen from '../screens/HomeScreen'
import ProfileScreen from '../screens/ProfileScreen'
import CocktailDetailScreen from '../screens/CocktailDetailScreen'
import PublishRecipeScreen from '../screens/PublishRecipeScreen'
const DrawerNavigator = () => {
const Drawer = createDrawerNavigator()
return (
<Drawer.Navigator>
<Drawer.Screen name='Home' component={HomeScreen} options={{headerShown: false}} />
<Drawer.Screen name='Profile' component={ProfileScreen} options={{headerShown: false}} />
<Drawer.Screen name='CocktailDetail' component={CocktailDetailScreen} options={{headerShown: false}} />
<Drawer.Screen name='PublishRecipe' component={PublishRecipeScreen} options={{headerShown: false}} />
</Drawer.Navigator>
)
}
export default DrawerNavigator
I still find this a bit confusing though, and I guess there's probably a simpler way to write this.
Useful resources I've found on this topic:
https://reactnavigation.org/docs/nesting-navigators/
https://blog.waldo.io/combining-navigators-in-react-navigation/

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

Im getting the following issue:
The action 'NAVIGATE' with payload {"name":"EditProfileScreen"} was not handled by any navigator.
Do you have a screen named 'EditProfileScreen'?
My code:
settingsNavigator.js
import React from 'react';
import { createStackNavigator } from "#react-navigation/stack";
import SettingsScreen from "../screens/settingsScreen";
import EditProfileScreen from "../screens/editProfileScreen"
const SettingsStack = createStackNavigator();
const SettingsNavigator = () => (
<SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} options={{ headerShown: false }} />
<SettingsStack.Screen name="EditProfileScreen" component={EditProfileScreen} options={{ title: 'Edit Profile' }} />
</SettingsStack.Navigator>
)
export default SettingsNavigator
settingScreen.js
import React from 'react';
import { Text, StyleSheet, TouchableOpacity, Linking } from 'react-native';
import { Card } from 'react-native-paper'
import Screen from '../Components/Screen'
function SettingsScreen({navigation}) {
return (
<Screen style={styles.screen}>
<TouchableOpacity onPress={() => navigation.navigate("EditProfileScreen")}>
<Card style={styles.list} >
<Text>Edit Profile</Text>
</Card>
</TouchableOpacity>
</Screen>
)
}
const styles = StyleSheet.create({
list: {
padding: 20,
backgroundColor: 'white',
borderRadius: 5,
marginTop: 10,
},
})
export default SettingsScreen
editProfileScreen
import React from 'react';
import { Text, StyleSheet} from 'react-native';
import Screen from '../Components/Screen'
function EditProfileScreen({navigation}) {
return (
<Screen style={styles.screen}>
<Text>Edit Profile Screen</Text>
</Screen>
)
}
const styles = StyleSheet.create({
})
export default EditProfileScreen
I have tried wrapping my settingNavigation in a NavigationContainer, but thats not working.
You need to return JSX in settingsNavigator.js file
const SettingsNavigator = () => (
return (
<SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} options={{ headerShown: false }} />
<SettingsStack.Screen name="EditProfileScreen" component={EditProfileScreen} options={{ title: 'Edit Profile' }} />
</SettingsStack.Navigator>
);
)
const SettingsNavigator = () => {
return <SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} options={{ headerShown: false }} />
<SettingsStack.Screen name="EditProfileScreen" component={EditProfileScreen} options={{ title: 'Edit Profile' }} />
</SettingsStack.Navigator>
}
Add return this type