I made a nested navigation Drawer + Stack, but the drawer is not working, I am not able to toggle the drawer, but able to drag the drawer from the left side and it goes back closing automatically after releasing it.
Also, I get a pop up when hovering over navigation.toggleDrawer(), this is what I get
Property 'toggleDrawer' does not exist on type
'NavigationProp<ParamListBase, string, Readonly<{ key: string; index:
number; routeNames: string[]; history?: unknown[]; routes:
NavigationRoute<ParamListBase, string>[]; type: string; stale: false;
}>, {}, {}>'
So what's wrong here and how to fix it? And can I make a drawer without using #react-navigation/drawer ?
app.js :
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import HomeScreen from "./src/screens/HomeScreen";
import MovieScreen from "./src/screens/MovieScreen";
import FavoriteScreen from "./src/screens/FavoritesScreen";
import { useFonts } from "expo-font";
import AppLoading from "expo-app-loading";
import { createDrawerNavigator } from "#react-navigation/drawer";
import CustomDrawerContent from "./src/components/DrawerContent";
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
function HomeStackScreen() {
return (
<Stack.Navigator>
<Stack.Screen
name='home'
component={HomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name='movie'
component={MovieScreen}
options={{ headerShown: false }}
/>
</Stack.Navigator>
);
}
export default () => {
const [fontLoaded] = useFonts({
Regular: require("./assets/fonts/NunitoSans-Regular.ttf"),
Bold: require("./assets/fonts/NunitoSans-Bold.ttf"),
Black: require("./assets/fonts/NunitoSans-Black.ttf"),
ExtraBold: require("./assets/fonts/NunitoSans-ExtraBold.ttf"),
ExtraLight: require("./assets/fonts/NunitoSans-ExtraLight.ttf"),
Light: require("./assets/fonts/NunitoSans-Light.ttf"),
SemiBold: require("./assets/fonts/NunitoSans-SemiBold.ttf"),
});
return fontLoaded ? (
<NavigationContainer>
<Drawer.Navigator
drawerContent={(props) => <CustomDrawerContent {...props} />}
initialRouteName='Home'
screenOptions={{ drawerPosition: "left", drawerType: "front" }}
>
<Drawer.Screen
name='home'
component={HomeStackScreen}
options={{ headerShown: false }}
/>
<Drawer.Screen
name='fav'
component={FavoriteScreen}
options={{ headerShown: false }}
/>
</Drawer.Navigator>
</NavigationContainer>
) : (
<AppLoading />
);
};
home.js
import { useNavigation } from "#react-navigation/native";
export default function HomeScreen(){
const navigation = useNavigation();
return(
<ScrollView style={styles.container}>
<StatusBar
style='auto'
translucent={false}
backgroundColor={COLORS.BASIC_BACKGROUND}
/>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 20,
paddingVertical: 10,
}}
>
<Pressable
style={{ flex: 1 }}
onPress={() => {
navigation.toggleDrawer();
console.log("Clicked on Menu Bar");
}}
>
<Image
style={{ width: 25, height: 28 }}
source={{
uri: "https://img.icons8.com/material-rounded/96/000000/menu--v1.png",
}}
/>
</Pressable>
</View>
</ScrollView>
)
}
Related
I have a nested navigator, Drawer navigator then stack navigator,
When user is on a screen on the home stack, other than the root screen of the home stack, when user opens drawer and click on Home, it should redirect to the root of the home stack.
How can I achieve this?
Below is code for my drawer navigator and Home stack
drawer:
import {
createDrawerNavigator,
DrawerItemList,
} from "#react-navigation/drawer";
import Bg from "../../assets/background.png";
import { NavigationContainer } from "#react-navigation/native";
import Home from "../screens/home";
import { ImageBackground, SafeAreaView, Text, View } from "react-native";
import HomeStack from "./homeStack";
import { SafeAreaProvider } from 'react-native-safe-area-context';
import SongStack from "./songStack";
import SearchStack from "./searchStack";
import ContactUsStack from "./contactUsStack";
import HelpStack from "./helpStack";
import VolunteerStack from "./volunteerStack";
const CustomDrawerContentComponent = (props) => (
<ImageBackground style={{ flex: 1, resizeMode: "cover" }} source={Bg}>
<View
style={{
backgroundColor: "rgba(59, 82, 88,0.65)",
width: "100%",
height: "100%",
}}
>
<SafeAreaView>
<View style={{ height: "10%" }}></View>
<DrawerItemList {...props} />
</SafeAreaView>
<Text
style={{ position: "absolute", bottom: 1, left: 1, color: "#ffffff" }}
>
Copyright © Songs Of Zion v4.1.1 {new Date().getFullYear()}
</Text>
</View>
</ImageBackground>
);
const Drawer = createDrawerNavigator();
export default function Draweri() {
return (
<SafeAreaProvider>
<NavigationContainer>
<Drawer.Navigator
drawerContent={(props) => <CustomDrawerContentComponent {...props} />}
screenOptions={{
unmountOnBlur:true,
headerShown: false,
drawerItemStyle: {
borderColor: "white",
borderBottomWidth: 1.5,
},
drawerActiveTintColor: "#ffffff",
drawerInactiveTintColor: "#ffffff",
drawerActiveBackgroundColor: "rgba(59, 82, 88,0.7)",
drawerLabelStyle: {
fontSize: 18,
marginLeft: 20,
marginTop: 20,
marginBottom: 20,
},
}}
>
<Drawer.Screen name="DHome" options={{title:"Home"}} component={HomeStack} />
<Drawer.Screen name="Song" component={SongStack} />
<Drawer.Screen name="Search" options={{unmountOnBlur: true}} component={SearchStack} />
<Drawer.Screen name="ContactUs"options={{title:"Contact Us"}} component={ContactUsStack} />
<Drawer.Screen name="Help" component={HelpStack} />
<Drawer.Screen name="Volunteer" component={VolunteerStack} />
</Drawer.Navigator>
</NavigationContainer>
</SafeAreaProvider>
);
}
Home Stack:
import { createNativeStackNavigator } from "#react-navigation/native-stack";
import Home from "../screens/home";
import SearchResults from "../shared/screens/search/searchResults";
import Header from "../shared/header";
import Search from "../screens/search";
import Sync from "../screens/home/sync";
import Song from "../shared/screens/song";
const Stack = createNativeStackNavigator();
export default function HomeStack(navigation) {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
options={{ headerShown: false }}
/>
<Stack.Screen name="SearchResults" component={SearchResults} options={{header: ({navigation}) => <Header navigation={navigation} title={"Search Results"} pop={true} />}}/>
<Stack.Screen name="SongLyrics" component={Song} options={{header: ({navigation}) => <Header navigation={navigation} title={"Song Lyrics"} pop={true} replace={true} />}}/>
<Stack.Screen name="Search" component={Search} options={{header: ({navigation}) => <Header navigation={navigation} title={"Search"} pop={true}/>}}/>
<Stack.Screen name="BookSongLyrics" component={Song} options={{header: ({navigation}) => <Header navigation={navigation} title={"Song Lyrics"} pop={true}/>}}/>
<Stack.Screen name="Sync" component={Sync} options={{ headerShown: false }}
/>
</Stack.Navigator>
);
}
I have tried:
<Drawer.Screen
name="Home"
component={HomeStack}
options={{
drawerLabel: 'Home',
// This will be called when the home button is pressed in the drawer
onPress: ({ navigation }) => {
// Reset the home stack to the 'Home' screen
navigation.reset({
index: 0,
routes: [{ name: 'Home' }],
});
},
}}
/>
....
function Home({ navigation }) {
useFocusEffect(
React.useCallback(() => {
// Reset the home stack to the 'Home' screen when the 'Home' screen becomes the focused screen
navigation.reset({
index: 0,
routes: [{ name: 'Home' }],
});
}, [navigation])
);
// Other component code
}
...
function App() {
return (
<Drawer.Navigator>
<Drawer.Screen
name="DHome"
component={HomeStack}
options={{
title: 'Home',
// This will be called when the home button is pressed in the drawer
onPress: ({ navigation }) => {
// Navigate to the Home screen
navigation.navigate('Home');
},
}}
/>
{/* Other screens in the drawer navigator */}
</Drawer.Navigator>
);
}
...
const CustomDrawerContentComponent = (props) => {
const { navigation } = props;
return (
<View>
<DrawerItemList
{...props}
onItemPress={({ route, focused }) => {
if (route.name === 'DHome') {
// Navigate to the root screen of the home stack when the home button is pressed
navigation.navigate('Home');
} else {
// Navigate to the pressed screen for other buttons
navigation.navigate(route.name);
}
}}
/>
</View>
);
};
const Drawer = createDrawerNavigator();
function App() {
return (
<Drawer.Navigator
drawerContent={(props) => <CustomDrawerContentComponent {...props} />}
>
<Drawer.Screen name="DHome" component={HomeStack} />
{/* Other screens in the drawer navigator */}
</Drawer.Navigator>
);
}
...
import { NavigationContainer } from '#react-navigation/native';
const Drawer = createDrawerNavigator();
function MyDrawer({ navigation }) {
return (
<NavigationContainer
onNavigationStateChange={(prevState, currentState) => {
const currentRouteName = currentState.routes[currentState.index].name;
if (currentRouteName === 'Home') {
// Navigate to the root screen of the home stack when the home button is pressed
navigation.navigate('Home');
} else {
// Navigate to the pressed screen for other buttons
navigation.navigate(currentRouteName);
}
}}
>
<Drawer.Navigator>
<Drawer.Screen name="Home" component={HomeStack} />
<Drawer.Screen name="Song" component={SongStack} />
<Drawer.Screen name="Search" component={SearchStack} />
<Drawer.Screen name="ContactUs" component={ContactUsStack} />
<Drawer.Screen name="Help" component={HelpStack} />
<Drawer.Screen name="Volunteer" component={VolunteerStack} />
</Drawer.Navigator>
</NavigationContainer>
);
}
I have an issue with react navigation.
I would like to have the same behavior as the linkedIn app has.
I mean, in that app, you can open the settings page from the drawer in differents tabs. You can open it from the first tab, second one... and so on. and at the end you get multiple instances.
I am not able to reproduce this behavior
My navigation is:
One drawer with one drawer screen (one Tab navigator inside). 3 tabs screens inside that Tab navigator. Each one contains a stack. I have set the same screens in that screen. For example I want to share the Profile, so I have one profile screen in each tab.
In the customDrawer I navigate to screens name, but here is the problem. React navigation does not know what stack should call before calling the right screen.
And I cannot find a way to know the current mounted stack so I cannot set it dinamically in order to do inside the custom drawer:
onPress={() =>
props.navigation.navigate(Routes.student.home.STACK, { screen: Routes.student.SETTINGS })
}
Thanks!
App.tsx
/* eslint-disable react-native/no-inline-styles */
import 'react-native-gesture-handler';
import React from 'react';
import { Text } from 'react-native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItem,
} from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
import { QueryClient, QueryClientProvider } from '#tanstack/react-query';
import { StatusBar } from 'expo-status-bar';
import HomeStackScreen from '#pages/Home';
import { Routes } from '#src/constants/routes';
import { PracticalStackScreen } from '#src/pages/Practical/Practical';
import { TheoryStackScreen } from '#src/pages/Theory/Theory';
// Create a client
const queryClient = new QueryClient();
const Tab = createBottomTabNavigator();
const Drawer = createDrawerNavigator();
const TabNavigator = () => {
return (
<Tab.Navigator
screenOptions={{ headerShown: false }}
initialRouteName={Routes.student.home.STACK}
>
<Tab.Screen
name={Routes.student.theory.STACK}
component={TheoryStackScreen}
options={{ title: 'TEÓRICO' }}
/>
<Tab.Screen
name={Routes.student.home.STACK}
component={HomeStackScreen}
options={{ title: '' }}
/>
<Tab.Screen
name={Routes.student.practical.STACK}
component={PracticalStackScreen}
options={{ title: 'PRÁCTICO' }}
/>
</Tab.Navigator>
);
};
function CustomDrawerContent(props: any) {
console.log('props ', props);
return (
<DrawerContentScrollView {...props}>
<Text>Mi cuenta</Text>
<DrawerItem
label='Configuración'
onPress={() => props.navigation.navigate(Routes.student.SETTINGS)}
/>
<DrawerItem
label='Métodos de pago'
onPress={() => props.navigation.navigate(Routes.student.PAYMENT)}
/>
<Text>Social</Text>
<DrawerItem
label='Tiktok'
onPress={() => props.navigation.navigate(Routes.student.PROFILE)}
/>
<Text>Ayuda</Text>
<DrawerItem
label='Preguntas frecuentes'
onPress={() => props.navigation.navigate(Routes.student.FAQ)}
/>
<DrawerItem
label='Atención al alumno'
onPress={() => props.navigation.navigate(Routes.student.STUDENT_SUPPORT)}
/>
</DrawerContentScrollView>
);
}
const DrawerNavigation = () => {
return (
<Drawer.Navigator
useLegacyImplementation={true}
drawerContent={(props) => <CustomDrawerContent {...props} />}
initialRouteName={Routes.student.home.STACK}
>
<Drawer.Screen name={Routes.MAIN_TAB} component={TabNavigator} />
</Drawer.Navigator>
);
};
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<StatusBar />
<NavigationContainer>
<DrawerNavigation />
</NavigationContainer>
</QueryClientProvider>
);
}
Home.tsx
/* eslint-disable react-native/no-color-literals */
import React from 'react';
import { StyleSheet, Text, View, Pressable } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { Routes } from '#src/constants/routes';
import Faq from '../Faq';
import Payment from '../Payment';
import Profile from '../Profile';
import Settings from '../Settings';
import StudentSupport from '../StudentSupport';
const HomeStack = createNativeStackNavigator();
export const HomeStackScreen = (): JSX.Element => {
return (
<HomeStack.Navigator
screenOptions={{ headerStyle: { backgroundColor: 'red' }, headerShown: false }}
>
<HomeStack.Screen name={Routes.student.home.MAIN} component={Home} />
<HomeStack.Screen name={Routes.student.PROFILE} component={Profile} />
<HomeStack.Screen name={Routes.student.SETTINGS} component={Settings} />
<HomeStack.Screen name={Routes.student.PAYMENT} component={Payment} />
<HomeStack.Screen name={Routes.student.FAQ} component={Faq} />
<HomeStack.Screen name={Routes.student.STUDENT_SUPPORT} component={StudentSupport} />
</HomeStack.Navigator>
);
};
export const Home = ({ navigation }: any): JSX.Element => (
<View style={styles.container}>
<Text>Home Screen</Text>
<Pressable style={styles.button} onPress={() => navigation.navigate(Routes.student.PROFILE)}>
<Text style={styles.text}>Perfil</Text>
</Pressable>
</View>
);
const backgroundColor = '#fff';
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: 'grey',
borderRadius: 4,
elevation: 3,
justifyContent: 'center',
paddingHorizontal: 32,
paddingVertical: 12,
},
container: {
alignItems: 'center',
backgroundColor,
flex: 1,
justifyContent: 'center',
},
text: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
letterSpacing: 0.25,
lineHeight: 21,
},
});
Theroy.tsx
import React from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { Routes } from '#src/constants/routes';
import Faq from '../Faq';
import Payment from '../Payment';
import Profile from '../Profile';
import Settings from '../Settings';
import StudentSupport from '../StudentSupport';
const TheoryStack = createNativeStackNavigator();
export const TheoryStackScreen = (): JSX.Element => {
return (
<TheoryStack.Navigator
screenOptions={{ headerStyle: { backgroundColor: 'red' }, headerShown: false }}
>
<TheoryStack.Screen name={Routes.student.theory.MAIN} component={Theory} />
<TheoryStack.Screen name={Routes.student.PROFILE} component={Profile} />
<TheoryStack.Screen name={Routes.student.SETTINGS} component={Settings} />
<TheoryStack.Screen name={Routes.student.PAYMENT} component={Payment} />
<TheoryStack.Screen name={Routes.student.FAQ} component={Faq} />
<TheoryStack.Screen name={Routes.student.STUDENT_SUPPORT} component={StudentSupport} />
</TheoryStack.Navigator>
);
};
export function Theory({ navigation }: any): JSX.Element {
return (
<View style={styles.container}>
<Text>Theory Screen</Text>
<Button title='Go to Home' onPress={() => navigation.navigate(Routes.student.home.STACK)} />
<Button
title='Go to Practical'
onPress={() => navigation.navigate(Routes.student.practical.STACK)}
/>
<Button
title='Go to Profile'
onPress={() =>
navigation.navigate(Routes.student.home.STACK, { screen: Routes.student.PROFILE })
}
/>
</View>
);
}
const backgroundColor = '#fff';
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor,
flex: 1,
justifyContent: 'center',
},
});
Practical.tsx
import React from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { Routes } from '#src/constants/routes';
import Faq from '../Faq';
import Payment from '../Payment';
import Profile from '../Profile';
import Settings from '../Settings';
import StudentSupport from '../StudentSupport';
const PracticalStack = createNativeStackNavigator();
export const PracticalStackScreen = (): JSX.Element => {
return (
<PracticalStack.Navigator
screenOptions={{ headerStyle: { backgroundColor: 'red' }, headerShown: false }}
>
<PracticalStack.Screen name={Routes.student.practical.MAIN} component={Practical} />
<PracticalStack.Screen name={Routes.student.PROFILE} component={Profile} />
<PracticalStack.Screen name={Routes.student.SETTINGS} component={Settings} />
<PracticalStack.Screen name={Routes.student.PAYMENT} component={Payment} />
<PracticalStack.Screen name={Routes.student.FAQ} component={Faq} />
<PracticalStack.Screen name={Routes.student.STUDENT_SUPPORT} component={StudentSupport} />
</PracticalStack.Navigator>
);
};
export function Practical({ navigation }: any): JSX.Element {
return (
<View style={styles.container}>
<Text>Practical Screen</Text>
<Button title='Go to Home' onPress={() => navigation.navigate(Routes.student.home.STACK)} />
<Button
title='Go to Theory'
onPress={() => navigation.navigate(Routes.student.theory.STACK)}
/>
<Button
title='Go to Profile'
onPress={() =>
navigation.navigate(Routes.student.home.STACK, { screen: Routes.student.PROFILE })
}
/>
</View>
);
}
const backgroundColor = '#fff';
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor,
flex: 1,
justifyContent: 'center',
},
});
Try renaming your Settings screen component differently for each stack navigator. So something like
<PracticalStack.Screen name="Practical/Settings" component={Settings} />
<HomeStack.Screen name="Home/Settings" component={Settings} />
Then you could navigate to the appropriate screen from your drawer based on the tab in focus.
I think I found a possible solution to my question. I have changed the CustomDrawerContent.
function CustomDrawerContent(props: any) {
const drawerState = props.state.routes[0]?.state;
const routeIndex = drawerState?.index;
const focusedTab = drawerState?.routes?.[routeIndex]?.name || Routes.student.home.STACK;
return (
<DrawerContentScrollView {...props}>
<Text>Mi cuenta</Text>
<DrawerItem
label='Configuración'
onPress={() => props.navigation.navigate(focusedTab, { screen: Routes.student.SETTINGS })}
/>
<DrawerItem
label='Métodos de pago'
onPress={() => props.navigation.navigate(focusedTab, { screen: Routes.student.PAYMENT })}
/>
<Text>Social</Text>
<DrawerItem
label='Tiktok'
onPress={() => props.navigation.navigate(focusedTab, { screen: Routes.student.PROFILE })}
/>
<Text>Ayuda</Text>
<DrawerItem
label='Preguntas frecuentes'
onPress={() => props.navigation.navigate(focusedTab, { screen: Routes.student.FAQ })}
/>
<DrawerItem
label='Atención al alumno'
onPress={() =>
props.navigation.navigate(focusedTab, { screen: Routes.student.STUDENT_SUPPORT })
}
/>
</DrawerContentScrollView>
);
}
I am working on a React Native Expo app where I have both Stack Navigation and Drawer Navigation.
I have nested Drawer Navigator inside my Stack Navigator in app.js. When I click on Drawer hamburger menu, it opens the drawer from the right hand side. It was working fine on all the screens without any issue.
The problem occured when I decided to use this.props.navigation.push("Payment") to push to payment screen.
OpenDrawer() function is not passed as part of a prop when using navigation.push() whereas its working fine when using navigation.navigate().
OpenDrawer() function works in the payment screen when I navigate to that screen using below statement
this.props.navigation.navigate("Payment");
OpenDrawer() function throws function not found error when I navigate to that screen using below statement
this.props.navigation.push("Payment");
Below is my app.js where i nested drawer inside stack navigator. Can someone please advise how to resolve the issue. Thanks !!!
app.js
import React from "react";
import {
Dimensions,
ScrollView,
Button,
View,
SafeAreaView,
} from "react-native";
import { createStackNavigator } from "#react-navigation/stack";
import {
createDrawerNavigator,
DrawerContentScrollView,
} from "#react-navigation/drawer";
import {
NavigationContainer,
useNavigation,
DrawerItem,
} from "#react-navigation/native";
import Landingzone from "./components/Landingzone";
import LandingPage from "./components/LandingPage";
import Summary from "./components/Summary";
import Payment from "./components/Payment";
import { TouchableOpacity } from "react-native-gesture-handler";
import { Icon, Text } from "react-native-elements";
const myFont = Platform.OS === "ios" ? "Arial" : "sans-serif";
let myFontSize = 15;
const SCREEN_WIDTH = Dimensions.get("window").width;
if (SCREEN_WIDTH > 300 && SCREEN_WIDTH <= 360) {
myFontSize = 10;
} else if (SCREEN_WIDTH > 300 && SCREEN_WIDTH <= 415) {
}
export default function App() {
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const DrawerNavigator = () => (
<Drawer.Navigator
drawerPosition="right"
drawerContentOptions={{
labelStyle: {
color: "white",
fontFamily: myFont,
fontSize: 16,
},
}}
drawerStyle={{
backgroundColor: "#343a40",
flex: 1,
flexDirection: "column",
}}
drawerContent={(props) => (
<DrawerContentScrollView
contentContainerStyle={{
flex: 1,
flexDirection: "column",
}}
>
<View
style={{
flex: 0.15,
}}
>
<Icon
reverse
name="user-circle-o"
type="font-awesome"
color="#517fa4"
containerStyle={{
backgroundColor: "green",
left: 115,
}}
/>
<Text>SaimugaTutorials#gmail.com</Text>
</View>
<View
style={{
flex: 0.1,
justifyContent: "center",
}}
>
<Text>Enroll</Text>
</View>
</DrawerContentScrollView>
)}
>
<Drawer.Screen
name="Summary"
component={Summary}
options={{ headerShown: false }}
/>
<Drawer.Screen
name="Payment"
component={Payment}
options={{ headerShown: false }}
/>
</Drawer.Navigator>
);
const StackNavigator = () => (
<Stack.Navigator initialRouteName="Welcome">
<Stack.Screen
name="Welcome"
component={LandingPage}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Payment"
component={Payment}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Summary"
component={DrawerNavigator}
options={{ headerShown: false, gestureEnabled: false }}
/>
</Stack.Navigator>
);
return (
<NavigationContainer>
<StackNavigator />
</NavigationContainer>
);
}
I am using Drawer,Stack and Tab navigator using React Navigation 5, I have followed documentation but Tab Navigator not showing.
Here's my code:
In my app.js I have called my main StackNavigator:
const Stack = createStackNavigator();
export default class App extends React.Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator headerMode="none" initialRouteName="HomePage">
<Stack.Screen name="Home" component={HomePage} />
<Stack.Screen name="Login" component={LoginSignUp} />
<Stack.Screen name="DrawerScreenss" component={DrawerScreens} />
<Stack.Screen name="Tab" component={TabComp} />
</Stack.Navigator>
</NavigationContainer>
);
}
}
This is my Drawer Navigation Code:
import * as React from 'react';
import { createDrawerNavigator } from '#react-navigation/drawer';
import DrawerContent from './DrawerComponents/DrawerContent';
import DrawerHome from './DrawerComponents/DrawerHome';
const Drawer = createDrawerNavigator();
export default class DrawerScreens extends React.Component {
render() {
return (
<Drawer.Navigator
drawerContent={() => (
<DrawerContent navigation={this.props.navigation} />
)}>
<Drawer.Screen name="DrawHome" component={DrawerHome} />
</Drawer.Navigator>
);
}
}
Here's my TabNavigator which is not working:
import React, { Component } from "react";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import DrawerHome from "./DrawerHome";
import Bookmarks from "./Bookmarks";
export default class TabComp extends Component {
render() {
const Tab = createBottomTabNavigator();
return (
<Tab.Navigator
initialRouteName="Home"
tabBarOptions={{
activeTintColor: "#e91e63",
activeTintColor: "red",
inactiveTintColor: "grey",
style: {
backgroundColor: "white",
borderTopColor: "red"
},
labelStyle: {
fontSize: 12,
fontWeight: "normal"
},
indicatorStyle: {
borderBottomColor: "red",
borderBottomWidth: 4
}
}}
>
<Tab.Screen name="Home" component={DrawerHome} />
<Tab.Screen name="Bookmarks" component={Bookmarks} />
</Tab.Navigator>
);
}
}
It should be visible in my DrawerHome screens but not working
I don't know exactly what your HomePage component looks like, but it could look something like this with a button that navigates to your DrawerScreens screen:
const HomePage = ({navigation}) => {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Feed Screen</Text>
<Button
title="Go to DrawerScreens"
onPress={() => navigation.navigate('DrawerScreens')}
/>
</View>
);
};
The important thing I changed in your DrawerScreens component is that its screen is your TabComp component:
class DrawerScreens extends React.Component {
render() {
return (
<Drawer.Navigator
drawerContent={() => (
<DrawerContent navigation={this.props.navigation} />
)}>
<Drawer.Screen name="Tab" component={TabComp} />
</Drawer.Navigator>
);
}
}
The TabComp component itself can stay the same.
Then inside your DrawerHome component you can trigger your drawer using navigation.openDrawer().
const DrawerHome = ({navigation}) => {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Feed Screen</Text>
<Button title="Open Drawer" onPress={() => navigation.openDrawer()} />
</View>
);
};
This way you can show your tabs and your drawer at the same time.
When I swipe right my drawer opens, but I want it to open using a button in the header. I have place the DrawerNavigator 'createDrawer ' in side the StackNavigator'createHomeStack'.
I am getting this error:
Reference Error: Can't find variable : Navigation
I also tried this: options={({ navigation }) => ({ but then I get error:
TypeError: navigation.toggleDrawer is not a function. (In 'navigation.toggleDrawer()', 'navigation.toggleDrawer' is undefined)
Code:
import React from 'react';
import { TouchableOpacity } from 'react-native';
import {
NavigationContainer,
DrawerActions,
DefaultTheme,
DarkTheme,
useNavigation,
} from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { createStackNavigator } from '#react-navigation/stack';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {
Appearance,
useColorScheme,
AppearanceProvider,
} from 'react-native-appearance';
import Feed from './src/feed';
import Detail from './src/detail';
import Screen1 from './src/screens/drawer/screen1';
import Screen2 from './src/screens/drawer/screen2';
import Screen3 from './src/screens/drawer/screen3';
import Tab1 from './src/screens/tabs/tab1';
import Tab2 from './src/screens/tabs/tab2';
const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();
App = () => {
const colorScheme = useColorScheme();
const MyTheme = {
dark: false,
colors: {
primary: 'white',
background: 'white',
card: '#65509f',
text: 'white',
border: 'green',
},
};
createHomeStack = () => (
<Stack.Navigator>
<Stack.Screen
name='Home'
children={this.createDrawer}
options={{
title: 'Home Screen',
headerLeft: () => (
<TouchableOpacity onPress={() => navigation.toggleDrawer()}>
<Icon
name='menu'
style={[{ color: 'white', marginLeft: 16 }]}
size={25}
></Icon>
</TouchableOpacity>
),
}}
/>
<Stack.Screen
name='Detail'
component={Detail}
options={{
title: 'Detail Screen',
}}
/>
<Stack.Screen name='Bottom Tabs' component={Tab1} />
<Stack.Screen name='Top Tabs' component={Tab2} />
</Stack.Navigator>
);
createDrawer = () => (
<Drawer.Navigator>
<Drawer.Screen name='Feed' component={Feed} />
<Drawer.Screen name='Contacts' component={Screen1} />
<Drawer.Screen name='Favorites' component={Screen2} />
<Drawer.Screen name='Settings' component={Screen3} />
</Drawer.Navigator>
);
return (
<AppearanceProvider>
<NavigationContainer theme={colorScheme == 'dark' ? DarkTheme : MyTheme}>
{this.createHomeStack()}
</NavigationContainer>
</AppearanceProvider>
);
};
export default App;
There are 2 approaches to handle this:
Nest the stack inside the drawer instead of drawer inside stack
Use dispatch instead of toggleDrawer:
import { DrawerActions } from '#react-navigation/native';
// ...
<TouchableOpacity onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}>
Read more about how nesting works here https://reactnavigation.org/docs/nesting-navigators#navigator-specific-methods-are-available-in-the-navigators-nested-inside
import { DrawerActions } from '#react-navigation/native';
// ...
options={({ navigation }) => ({
title: 'Home Screen',
headerLeft: () => (
<TouchableOpacity style={{ paddingLeft: 20 }}>
<Icon
name='menu'
size={25}
style={[{ color: 'black' }]}
onPress={() =>
navigation.dispatch(DrawerActions.toggleDrawer())
}
/>
</TouchableOpacity>
),
})}
You need to get navigation prop from option the dispatch drawer Action when Button is pressed. Try the below code:
options={({navigation}) => ({
title: 'Home Screen',
headerLeft: () => (
<TouchableOpacity onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}>
<Icon
name='menu'
style={[{ color: 'white', marginLeft: 16 }]}
size={25}
></Icon>
</TouchableOpacity>
),
})}