React Navigator, undefined is not an object - react-native

Anyone know why I cant call toggleDrawer on navigation from my Header here? I assume that the navigation prop should be provided by default to Drawer.Navigator, but it seems to be undefined.
App.js
import { NavigationContainer, DefaultTheme, DrawerActions } from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import HomeScreen from './screens/HomeScreen';
import Header from './components/Header';
import Background from './components/Background';
const theme = {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
background: 'transparent',
},
};
const Drawer = createDrawerNavigator()
export default function App() {
return (
<NavigationContainer theme={theme} >
<Background />
<Drawer.Navigator initialRouteName="Home" screenOptions={{ header: () => <Header options={{headerStyle: {height: 200}}} /> }}>
<Drawer.Screen name="Home" component={HomeScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
Header.js
const Header = ( {navigation, route, options, back}) => {
const [fontsLoaded] = useFonts({Kanit_400Regular, Kanit_500Medium, Kanit_700Bold})
if (!fontsLoaded) return <LoadingSpinner />
return (
<View style={options.headerStyle}>
<View style={styles.headerContainer}>
<TouchableOpacity style={styles.hamburgerContainer} onPress={() => navigation.toggleDrawer()} >
<View>
<View style={styles.hamburgerLine}></View>
<View style={styles.hamburgerLine}></View>
<View style={styles.hamburgerLine}></View>
</View>
</TouchableOpacity>
</View>
)
}
When I press the hamburger menu:

The navigation object will be passed to a custom header by the library. However, you are not passing the props to your custom component.
You can pass the props from the library to your header component as follows.
<Drawer.Navigator initialRouteName="Home" screenOptions={{ header: (props) => <Header {...props} options={{headerStyle: {height: 200}}} /> }}>
<Drawer.Screen name="Home" component={HomeScreen} />
</Drawer.Navigator>

Related

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
}
})

toggleDrawer from #react-navigation/drawer not working in React-Native

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>
)
}

Add a background image to a react navigation drawer

I'm trying to add a background image to a react navigation drawer
import React from "react";
import { createDrawerNavigator } from "#react-navigation/drawer";
import { StackNavigator } from "../../routes/HomeStack";
import { MaterialIcons } from "#expo/vector-icons";
import { DemonHunterIcon, DruidIcon} from "../../icons";
import { DemonHunter } from "../../screens/DemonHunter";
import { Druid } from "../../screens/Druid";
import { HomeHeader } from "../../components/Header";
import { ImageBackground } from "react-native";
const { Navigator, Screen } = createDrawerNavigator();
export default function Drawer() {
return (
<ImageBackground source={require("../../assets/drawer-bg.png")} style={{ flex: 1 }}>
<Navigator initialRouteName="Home" hideStatusBar>
<Screen
name="Home"
options={{
drawerIcon: () => <MaterialIcons name="home" size={24} color="black" />,
}}
>
{() => <StackNavigator component={Home} name="Home" header={HomeHeader} />}
</Screen>
<Screen
name="Hunter"
options={{
drawerIcon: () => <HunterIcon />,
}}
>
{() => <StackNavigator component={Hunter} name="Hunter" />}
</Screen>
<Screen name="Demon Hunter" options={{ drawerIcon: () => <DemonHunterIcon /> }}>
{() => <StackNavigator component={DemonHunter} name="Demon Hunter" />}
</Screen>
<Screen name="Druid" options={{ drawerIcon: () => <DruidIcon /> }}>
{() => <StackNavigator component={Druid} name="Druid" />}
</Screen>
</Navigator>
</ImageBackground>
);
}
Tried wrapping the drawer on tag but didn't work. Any clue on how to do this? I have searched a lot and didn't found a solution.
Also if you can tell me how to change the font family and color of the labels I'll be thankful :)

BottomTabNavigator not working in React Native

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.

react-navigation v5 - how to toggle drawer

I upgraded to react-navigation V5, and am so confused how to get the Drawer to work. I had a custom drawer before, but now I'm just trying to get a sample drawer working.
I am trying to open the drawer with this.props.navigation.dispatch(DrawerActions.toggleDrawer())
The action 'TOGGLE_DRAWER' was not handled by any navigator.
Is your screen inside a Drawer navigator?
Here are the relevant files:
MessagesStackRouter.js
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
function DrawerNavigation() {
return (
<Drawer.Navigator
drawerType={"slide"}
>
<Drawer.Screen name="Dash" component={DashboardContainer} />
</Drawer.Navigator>
);
}
function MessagesStackRouter() {
return (
<NavigationContainer>
<Stack.Navigator
initalRoute="Login"
screenOptions={{ gestureEnabled: true, headerShown: false }}
>
<Stack.Screen name="Login" component={LoginView} />
<Stack.Screen name="DrawerNavigation" component={DrawerNavigation} />
<Stack.Screen name="Dashboard" component={DashboardContainer} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default MessagesStackRouter;
App.js
return (
<View style={{flex:1, backgroundColor: 'white'}}>
<StatusBar hidden={true} />
<Provider store={createStore(reducers)}>
<MessagesScreenRouter/>
</Provider>
</View>
);
relevant parts of TopNavBar.js
import { DrawerActions } from '#react-navigation/native';
class TopNavBar extends Component {
constructor(props) {
super(props);
this.onBurgerBarPress = this.onBurgerBarPress.bind(this)
}
onBurgerBarPress() {
this.props.navigation.dispatch(DrawerActions.toggleDrawer())
}
render() {
return (
<View style={styles.navBar}>
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', marginTop: 10 }}>
<TouchableOpacity onPress={()=> this.onBurgerBarPress()}>
<Icon
name={"Menu"}
strokeWidth="1.5"
stroke={'#03A9F4' }
fill={'#03A9F4'}
/>
</TouchableOpacity>
</View>
</View>
)
}
};
const mapStateToProps = (state) => {
return {
onboarding: state.onboarding,
currentUser: state.currentUser
}
}
export default connect(mapStateToProps, actions)(TopNavBar);
You get an error because the screen where you have the drawer navigator is not rendered. You should nest the stack navigator inside the drawer navigator instead of drawer inside stack which will work better for your case.