How to open a drawer by clicking hamburger icon in header in react native? - react-native

This is my code:
import React from 'react';
import { Text, Block } from 'galio-framework';
import { StyleSheet } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
export default function Header(props) {
return (
<Block style={ styles.header }>
<Block>
<Ionicons name="md-menu" size={32} color="grey" onPress={() => navigation.openDrawer()} />
<Text style={ styles.title } p>{ props.title }</Text>
</Block>
<Block>
<Ionicons name="md-search" size={32} color="grey" />
</Block>
</Block>
)
}
When clicking on the hamburger icon I get this error:
RefererenceError: Can't find variable: Navigation
If I change my code to:
onPress={() => this.props.navigation.openDrawer()}
I get this error:
TypeError: undefined is not an object (evaluating '_this.props)
This is one of my files where I am importing Header:
import React, { Component } from 'react';
import { Text, Block, Input, Button, Card } from 'galio-framework';
import { StyleSheet, ScrollView, View } from 'react-native';
import Header from '../../common/Header';
class Accountant extends Component {
render() {
return (
<Block style={ styles.blockStyle }>
<Header title="Accounts" />
<Button onlyIcon icon="right" onPress={() => this.props.navigation.navigate('Projects')}>
</Button>
</Block>
);
}
}
I am using nested navigation. Here is my App.js file:
const Stack = createStackNavigator();
const DrawerAccountant = createDrawerNavigator();
function AccountantDrawer() {
return (
<DrawerAccountant.Navigator initialRouteName="Accountant">
<DrawerAccountant.Screen name="Accountant" component={AccountantScreen} />
<DrawerAccountant.Screen name="My Account" component={MyAccountScreen} />
</DrawerAccountant.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Stack.Screen name="Accountant" component={AccountantDrawer} />
<Stack.Screen name="Projects" component={ProjectsScreen} />
<Stack.Screen name="Tasks" component={TasksScreen} />
<Stack.Screen name="My Account" component={MyAccountScreen} />
</Stack.Navigator>
</NavigationContainer>
)
}
export default App;
The navigation drawer is working in the screens: "Accountant" and "My Account". The drawer opens when I click the menu icon in header. But it's not working in the screens: "Projects" and "Tasks".

Pass your navigation props to child component
<Header title="Accounts" navigation={this.props.navigation}/>
then you can access your navigation from Header as below
<Ionicons name="md-menu" size={32} color="grey" onPress={() => props.navigation.openDrawer()} />
or you can use withNavigation
Hope this helps you. Feel free for doubts.

Related

screens are not navigating in react native

I have a login screen then from there I navigate to home screen, and on home screen there are 4 buttons Alphabets, Ch-1,Ch-2 and Ch-3, by pressing each of those buttons, I can easily navigate to correct screens but Inside Alphabet screen, I have 2 more buttons Learn and Give test But when I press those, nothing happens , i can't navigate to the respective screens plus there are no errors. I guess its nested navigation.
I might sound stupid to an expert out there :) but I am new (from scratch) to react native and navigation stuff i really have no idea what to do! Will be really thankful if someone helps!
CODE IS GIVEN BELOW:
This is my home.js (its in folder screens):
import React from "react";
import {View, StyleSheet, Text} from 'react-native';
import { TouchableOpacity } from "react-native-gesture-handler";
import { Auth } from "../services";
export default home =({navigation}) => {
return (
<View style={styles.body}>
<Text style={styles.toptext}>
Merheba!
</Text>
<TouchableOpacity onPress={() => navigation.navigate('alphabets')}
style={styles.button}
>
<Text style={styles.buttontext}>Alphabets</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('ch1')}
style={styles.button}
>
<Text style={styles.buttontext}>Chapter 1</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('ch2')}
style={styles.button}
>
<Text style={styles.buttontext}>Chapter 2</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('ch3')}
style={styles.button}
>
<Text style={styles.buttontext}>Chapter 3</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => Auth.signOut()}
style={styles.button}
>
<Text style={styles.buttontext}>Sign Out</Text>
</TouchableOpacity>
</View>
)
}
This is index.js from screens folder:
export {default as home} from './home';
export {default as login} from './login';
export {default as forgotp} from './login';
export {default as signup} from './signup';
export {default as alphabets} from './alphabets';
export {default as alphl} from './alphl';
export {default as alpht} from './alpht';
export {default as ch1} from './ch1';
export {default as ch2} from './ch2';
export {default as ch3} from './ch3';
This is alphabets.js from screens folder:
import { NavigationContainer } from "#react-navigation/native";
import React from "react";
import {View, StyleSheet, Text} from 'react-native';
import { TouchableOpacity } from "react-native-gesture-handler";
export default alphabets =({navigation}) => {
return (
<View style={styles.body}>
<Text style={styles.toptext}>
Merheba!
</Text>
<TouchableOpacity onPress={() => navigation.navigate('alphl')}
style={styles.button}
>
<Text style={styles.buttontext}>Learning Sheet</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => navigation.navigate('alpht')}
style={styles.button}
>
<Text style={styles.buttontext}>Give Test</Text>
</TouchableOpacity>
</View>
)
}
AppNavigation.js from navigation folder:
import React from 'react';
import { createStackNavigator } from '#react-navigation/stack';
import home from '../screens/home';
import alphabets from '../screens/alphabets';
import ch1 from '../screens/ch1';
import ch2 from '../screens/ch2';
import ch3 from '../screens/ch3';
const stack=createStackNavigator();
export default AppNavigator = () => {
return(
<stack.Navigator
screenOptions={{
headerShown: null
}}
>
<stack.Screen name="home" component={home} />
<stack.Screen name="alphabets" component={alphabets} />
<stack.Screen name="ch1" component={ch1}/>
<stack.Screen name="ch2" component={ch2} />
<stack.Screen name="ch3" component={ch3} />
</stack.Navigator>
)
}
AlphNavigator.js from navigation folder:
import React from 'react';
import { createStackNavigator } from '#react-navigation/stack';
import alphl from '../screens/alphl';
import alpht from '../screens/alpht';
const stack=createStackNavigator();
export default AlphNavigator = () => {
return(
<stack.Navigator
screenOptions={{
headerShown: null
}}
>
<stack.Screen name="alphl" component={alphl} />
<stack.Screen name="alpht" component={alpht} />
</stack.Navigator>
)
}
& lastly index.js from navigation folder:
import React, {useState, useEffect} from 'react';
import { NavigationContainer } from '#react-navigation/native';
import AppNavigator from './AppNavigator';
import AuthNavigator from './AuthNavigator';
import auth from '#react-native-firebase/auth';
export default AppContainer = () => {
// Set an initializing state whilst Firebase connects
const [initializing, setInitializing] = useState(true);
const [user, setUser] = useState();
// Handle user state changes
function onAuthStateChanged(user) {
setUser(user);
if (initializing) setInitializing(false);
}
useEffect(() => {
const subscriber = auth().onAuthStateChanged(onAuthStateChanged);
return subscriber; // unsubscribe on unmount
}, []);
if (initializing) return null;
return(
<NavigationContainer>
{user ? <AppNavigator/> : <AuthNavigator/>}
</NavigationContainer>
)
}
You aren't defining your "AlphNavigator" in your "AppNavigator".
You should do this inside your AppNavigator:
export default AppNavigator = () => {
return(
<stack.Navigator
screenOptions={{
headerShown: null
}}
>
<stack.Screen name="home" component={home} />
<stack.Screen name="alphabets" component={alphabets} />
<stack.Screen name="alph" component={ AlphNavigator } /> /*here add your AlpNavigator*/
<stack.Screen name="ch1" component={ch1}/>
<stack.Screen name="ch2" component={ch2} />
<stack.Screen name="ch3" component={ch3} />
</stack.Navigator>
)}
It's normal that you do not have any error in this case, because React Navigation does not mark you as an error if a screen does not exist.
The above could be solved if you were using TypeScript.
So now, in order to access to nested navigation screens you should use:
navigation.navigate('alph', { screen: 'alphl' })
The first parameter is the name of the stack navigation, and the second one is an object with the name of the screen inside to this nested navigation.

React Native Navigation Error. How do I solve this?

In this block of code, I want to use navigation.navigate to switch between the home screen and the profile screen. But when I run the app, I get the following error: can't find variable navigation.
I've been looking for a solution, but I can't seem to find it.
Here's the code:
import 'react-native-gesture-handler';
import * as React from 'react';
import {View, Text, Button} from 'react-native';
import { NavigationContainer, StackActions } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const Stack = createStackNavigator();
const HomeScreen = () => {
return(
<View>
<Text>Home Screen</Text>
<Button title="Go to Profile Screen" onPress={()=> navigation.navigate("Profile")}/>
</View>
);
}
const ProfileScreen = () => {
return(
<View>
<Text>Profile Screen</Text>
<Button title="Go to Home Screen" onPress={() => navigation.navigate("Home")}/>
</View>
);
}
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Profile"
component={ProfileScreen}
options={{ title: '' }}
/>
<Stack.Screen
name="Home"
component={HomeScreen}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
Thank you in advance.
You can get navigation object from props. Code example:
const HomeScreen = ({navigation}) => {
return(
<View>
<Text>Home Screen</Text>
<Button title="Go to Profile Screen" onPress={()=> navigation.navigate("Profile")}/>
</View>
);
}

react-native-swiper doesnt support this.props.navigation.navigate

I am new to react native, I am trying to implement react-native-swiper to my project
render() {
return (
<Swiper
loop={false}
showsPagination={false}
index={1}>
<View style={this.viewStyle()}>
<ActivityScreen />
</View>
<Swiper
horizontal={true}
loop={false}
showsPagination={false}
index={1}>
<View style={this.viewStyle()}>
<YourGroups />
</View>
</Swiper>
<View style={this.viewStyle()}>
<AlertScreen />
</View>
</Swiper>
)
}
}
But when I am in component screen and click on the button
<Button title="thank you" onPress={()=>this.props.navigation.navigate("ThankScreen")} ></Button>
I get an error
undefined is not an object (evaluating 'this.props.navigation.navigate')
I ran in to the same issue and fixed it using React Navigation, 5 which allows you to access the navigation prop from any component using the useNavigation hook:
import React from 'react';
import { Button } from 'react-native';
import { useNavigation } from '#react-navigation/native';
const GoToButton = ({ screenName }) => {
const navigation = useNavigation();
return (
<Button
title={`Go to ${screenName}`}
onPress={() => navigation.navigate(screenName)}
/>
);
}

can't find variable navigation in other component in react-native

This is my App.js
import React from "react";
import Menu from "./components/Menu";
import HomeScreen from "./views/HomeScreen";
import SecondScreen from "./views/SecondScreen";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
const Stack = createStackNavigator();
export default function App() {
return (
<Container>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
/>
<Stack.Screen name="Second" component={SecondSCreen} />
</Stack.Navigator>
</NavigationContainer>
<Menu></Menu>
</Container>
);
}
It works, because it shows the HomeScreen on default, but I want to navigate to the second screen via the Menu-component:
import React from "react";
import { View, Text, TouchableOpacity } from "react-native";
class Menu extends React.Component {
render() {
return (
<View>
<TouchableOpacity
onPress={() => {
alert("Hi");
}}
>
<Text>HomeScreen</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
navigation.navigate("Second");
}}
>
<Text>Screen 2</Text>
</TouchableOpacity>
</View>
);
}
}
export default Menu;
The component is visible, but when I click on the second button I expect the SecondScreen to be openend.
But I get this error:
Can't find variable: navigation
What am I missing?
You should use the navigationRef for this scenario, as your menu is outside the navigation container
import { NavigationContainer } from '#react-navigation/native';
import { navigationRef } from './RootNavigation';
export default function App() {
return (
<Container>
<NavigationContainer ref={navigationRef}>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
/>
<Stack.Screen name="Second" component={SecondSCreen} />
</Stack.Navigator>
</NavigationContainer>
<Menu></Menu>
</Container>
);
}
// RootNavigation.js
import * as React from 'react';
export const navigationRef = React.createRef();
export function navigate(name, params) {
navigationRef.current?.navigate(name, params);
}
In menu js,
import {navigate} from 'RootNavigation';
class Menu extends React.Component {
render() {
return (
<View>
<TouchableOpacity
onPress={() => {
alert("Hi");
}}
>
<Text>HomeScreen</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
navigate("Second");
}}
>
<Text>Screen 2</Text>
</TouchableOpacity>
</View>
);
}
}

Drawer not navigating to next screen in React Native Navigation 5

I am using react native drawer with navigation 5, I have created a drawer but from the drawer when I click some of option to navigate to next screen it gives me error like "Undefined is not object.. this.props" and when I define prop on top like const navigation = this.props.navigation it then gives me error "Navigation is undefined..."
This is my Drawer where my content is placed:
export function DrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<View
style={
styles.drawerContent
}
>
<View style={styles.userInfoSection}>
<Avatar.Image
...
/>
</View>
<Drawer.Section style={styles.drawerSection}>
<DrawerItem
label="Preferences"
onPress={() => {}}
/>
<DrawerItem
label="Classes"
onPress={() => this.props.navigation.navigate('ClassHome')} //Over Here I want to navigation
/>
</Drawer.Section>
</View>
</DrawerContentScrollView>
);
}
And this is where I placed my Drawer Screens:
import * as React from 'react';
import { createDrawerNavigator } from '#react-navigation/drawer';
import HomeTimeTable from './HomeTimeTable';
import {DrawerContent} from './DrawerContent';
import ClassHome from './ClassHome';
const Drawer = createDrawerNavigator();
export default class DrawerScreens extends React.Component {
render(){
return (
<Drawer.Navigator drawerContent={() => <DrawerContent navigation = {this.props.navigation} />}>
<Drawer.Screen name="HomeTimeTable" component={HomeTimeTable} />
<Drawer.Screen name="ClassHome" component={ClassHome} />
</Drawer.Navigator>
);
}
}
You have to pass props from drawerContent to your DrawerContent as below :
import * as React from 'react';
import { createDrawerNavigator } from '#react-navigation/drawer';
import HomeTimeTable from './HomeTimeTable';
import {DrawerContent} from './DrawerContent';
import ClassHome from './ClassHome';
const Drawer = createDrawerNavigator();
export default class DrawerScreens extends React.Component {
render(){
return (
<Drawer.Navigator drawerContent={(props) => <DrawerContent {...props}/>}> {/* pass props here */}
<Drawer.Screen name="HomeTimeTable" component={HomeTimeTable} />
<Drawer.Screen name="ClassHome" component={ClassHome} />
</Drawer.Navigator>
);
}
}
Now, you can use that props directly in your custom component :
export function DrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
<View
style={
styles.drawerContent
}
>
<View style={styles.userInfoSection}>
<Avatar.Image
...
/>
</View>
<Drawer.Section style={styles.drawerSection}>
<DrawerItem
label="Preferences"
onPress={() => {}}
/>
<DrawerItem
label="Classes"
onPress={() => props.navigation.navigate('ClassHome')} // user props here
/>
</Drawer.Section>
</View>
</DrawerContentScrollView>
);
}
According to the documentation, the navigation prop should be passed by default to the DrawerContent. I would recommend doing it this way:
import * as React from 'react';
import { createDrawerNavigator } from '#react-navigation/drawer';
import HomeTimeTable from './HomeTimeTable';
import {DrawerContent} from './DrawerContent';
import ClassHome from './ClassHome';
const Drawer = createDrawerNavigator();
export default class DrawerScreens extends React.Component {
render(){
return (
<Drawer.Navigator drawerContent={DrawerContent}>
<Drawer.Screen name="HomeTimeTable" component={HomeTimeTable} />
<Drawer.Screen name="ClassHome" component={ClassHome} />
</Drawer.Navigator>
);
}
}