ReferenceError: Can't find variable: navigation - javascript

So what I'm trying to do is that I'd like the DrawerNavigator to be accessed by selecting the icon on the top left . Im using react nav 5 for this. I keep recieving the error displayed above.
I've tried doing this using this.props.navigation but that also did not seem to work.
Assistance would be greatly appreciared
AppNavigator:
/* eslint-disable no-unused-expressions */
import React, { useState, useEffect } from 'react'
import { NavigationContainer, DrawerActions } from '#react-navigation/native'
import { createStackNavigator } from '#react-navigation/stack'
import auth from '#react-native-firebase/auth'
import {IconButton} from 'react-native-paper'
import Login from '../components/login'
import Signup from '../components/signup'
import forgotPassword from '../components/forgotPassword'
import DashboardScreen from '../screens/DashboardScreen'
const Stack = createStackNavigator()
export default function MyStack() {
// Set state while Firebase Connects
const [starting, setStarting] = useState(true)
const [user, setUser] = useState()
// Handle state changes for user
function onAuthStateChanged(user) {
setUser(user)
if (starting) setStarting(false)
}
useEffect(() => {
const subcriber = auth().onAuthStateChanged(onAuthStateChanged)
return subcriber
// unsub on mount
}, [])
if (starting) return null
if (!user) {
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerTitleAlign: 'center',
headerStyle: {
backgroundColor: '#3740FE',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}}
>
<>
<Stack.Screen
name="Login"
component={Login}
/>
<Stack.Screen
name="Signup"
component={Signup}
/>
<Stack.Screen
name="ForgotPassword"
component={forgotPassword}
/>
</>
</Stack.Navigator>
</NavigationContainer>
)
}
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerTitleAlign: 'center',
headerStyle: {
backgroundColor: '#3740FE',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}}
>
<>
<Stack.Screen
name="Dashboard"
component={DashboardScreen}
options={{
headerLeft: props =>
<IconButton
{...props}
icon="menu"
color="white"
onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}
/>,
headerRight: props =>
<IconButton
{...props}
icon="magnify"
color="white"
/>
}}
/>
</>
</Stack.Navigator>
</NavigationContainer>
)
}
Dashboard:
import 'react-native-paper'
import React from 'react';
import { StyleSheet, View} from 'react-native';
import {Button} from 'react-native-paper'
import { createDrawerNavigator } from '#react-navigation/drawer'
function HomeScreen ({navigation}) {
return (
<View>
<Button
onPress={() => navigation.navigate('Settings')}
/>
</View>
);
}
function SettingsScreen ({navigation}) {
return (
<View> style={styles.container}
<Text>
TESTING
</Text>
</View>
);
}
const Drawer = createDrawerNavigator();
export default function DashboardScreen (){
return (
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen}/>
<Drawer.Screen name="Settings" component={SettingsScreen}/>
</Drawer.Navigator>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
display: "flex",
justifyContent: 'center',
alignItems: 'center',
padding: 35,
backgroundColor: '#fff'
},
textStyle: {
fontSize: 15,
marginBottom: 20
}
});

you can get it when you write the options in function like
<Stack.Screen
name="Dashboard"
component={DashboardScreen}
options={({navigation})=>({
headerLeft: props =>
<IconButton
{...props}
icon="menu"
color="white"
onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}
/>
})}
/>

Related

React Native Navigation: Can't find variable: navigation

I'm trying to make a parameter in the application header with access to the account settings, but when I recommend using navigation.navigate('Account')}, I get the Can't find variable: navigation error. I tried UseNavigation, but there he found the wrong use of hooks, and I did not understand how to do it correctly, and therefore I did not succeed through it.
Here are the code sources:
Header
App.js - he is in my case a navigator.
Header.js:
import { StyleSheet, Button, View, Text, Image, TouchableOpacity, Alert } from 'react-native';
import { useNavigation } from '#react-navigation/native'
export class Header extends Component {
render(){
return(
<View style={StyleInfo.container}>
<Text style={StyleInfo.TextStyle}> Store </Text>
<TouchableOpacity style={StyleInfo.ButtonStyle2} activeOpacity={0.5}>
<Image
source={require('./Icons/Notification.png')}
style={StyleInfo.buttonNotification}
/>
</TouchableOpacity>
<TouchableOpacity
style={StyleInfo.ButtonStyle}
activeOpacity={0.5}
onPress={() => navigation.navigate('Account')}
>
<Image
source={require('./Icons/IconACC.png')}
style={StyleInfo.buttonAcc}
/>
</TouchableOpacity>
</View>
);
}
}
const MenuStyle = StyleSheet.create({
menuContent: {
color: "#000",
fontWeight: "bold",
fontSize: 10,
}
});
App.js:
import { View, Button, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import Login from './src/screens/Login';
import HomeScreen from './src/screens/HomeScreen';
import Product from './src/screens/Product';
import Buy from './src/screens/Buy';
import Map from './src/screens/Map';
import Category from './src/screens/Category';
import StoreA from './src/screens/StoreA';
import Account from './src/screens/Account';
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Login" component={Login} options={{ headerShown: false }} />
<Stack.Screen options={{ headerShown: false }} name="HomeScreen" component={HomeScreen} />
<Stack.Screen name="Account" component={Account} options={{ title: 'Настройки аккаунта' }}/>,
})} />
<Stack.Screen name="Product" component={Product} options={{ title: 'Product' }}/>
<Stack.Screen name="Buy" component={Buy} options={{ title: 'Buy' }} />
<Stack.Screen name="Map" component={Map} options={{ title: 'Map' }} />
<Stack.Screen name="StoreA" component={StoreA} options={{ title: 'StoreA' }} />
<Stack.Screen name="Category" component={Category} options={{ title: 'Category' }} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
You might forgot const navigation = useNavigation();
And useNavigation is a hook, it will be better to use it in a function component.
Instead of using onPress={() => navigation.navigate('Account')} try to use it with the keyword "this".
onPress={() => this.navigation.navigate('Account')}
onPress={() => this.props.navigation.navigate('Account')}

React Native Navigation Drawer Problem ('navigation.openDrawer' is undefined))

Hi guys i'm new to react native. I want to use drawer navigation with menu button. But actually i don't understand react navigation very well probably. When i press button for openDrawer i'm getting error like this;
TypeError: navigation.openDrawer is not a function. (In 'navigation.openDrawer()', 'navigation.openDrawer' is undefined)
This is My Snack Example ; https://snack.expo.io/#vubes/drawer-check
Here is useful part of my code. Maybe you can understand my problem.
Thanks in advance to anyone who can help.
function DovizStack({navigation}) {
return (
<Stack.Navigator
initialRouteName="Döviz"
screenOptions={{
headerStyle: { backgroundColor: "#1D1D1D" },
headerTintColor: "#fff",
headerTitleStyle: { fontWeight: "bold" },
}}
>
<Stack.Screen
name="Doviz"
component={Doviz}
options={{
title: "Döviz",
headerTitleAlign: "center",
headerLeft: () => (<TouchableOpacity style={{paddingLeft:20}} onPress={()=> navigation.openDrawer()}>
<MaterialCommunityIcons name="menu" color={"white"} size={20} />
</TouchableOpacity>),
}}
/>
<Stack.Screen
name="dovizBuyDetails"
component={dovizBuyDetails}
options={{ title: "Alış", headerTitleAlign: "center" }}
/>
<Stack.Screen
name="dovizSellDetails"
component={dovizSellDetails}
options={{ title: "Satış", headerTitleAlign: "center" }}
/>
</Stack.Navigator>
);
}
I have 5 stack like this. After that comes the myTab.
drawerStack ;
function DrawerStack() {
return(
<Drawer.Navigator initialRouteName="Menu" drawerPosition= "right" >
<Drawer.Screen name="stack" component={stack} />
<Drawer.Screen name="Doviz" component={DovizStack}/>
<Drawer.Screen name="Altın" component={AltinStack} />
</Drawer.Navigator>
)
}
and default stack ;
export default function stack() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
options={{ headerShown: false }}
name="Giriş"
component={LandingStack}
/>
<Stack.Screen
options={{ headerShown: false }}
name="drawer"
component={myTab}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
Actually i can run drawer with landingscreen(login page,register) but i don't want to display without login
navigation in not defined in your scope.
use options as function and receive navigation see here.
your code should look like this:
<Stack.Screen
options={({ navigation }) => ({ //receive navigation here
//navigation is defined now you can use it
headerLeft: () => (
<TouchableOpacity
style={{paddingLeft:20}}
onPress={()=> navigation.openDrawer()}>
<MaterialCommunityIcons name="menu" color={"white"} size={20} />
</TouchableOpacity>),
})}
/>
EDIT :
see full example(open drawer menu from nested stack navigation) try snack here
import * as React from 'react';
import { Button, View, Text, TouchableOpacity } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
function ProfileScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Profile Screen</Text>
</View>
);
}
const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();
function DovizStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="Profile"
options={({ navigation }) => ({ //receive navigation here
headerLeft: () => (
<TouchableOpacity style={{paddingLeft:20}} onPress={()=> navigation.openDrawer()}>
<Text>open</Text>
</TouchableOpacity>),
})
}
component={ProfileScreen} />
</Stack.Navigator>
);
}
function DrawerStack() {
return(
<Drawer.Navigator initialRouteName="Doviz">
<Drawer.Screen name="Doviz" component={DovizStack}/>
</Drawer.Navigator>
)
}
export default function App() {
return (
<NavigationContainer>
<DrawerStack/>
</NavigationContainer>
);
}

How to navigate between 2 different navigators after login and logout in react native

I am a bit new to react native and I am having difficulty navigate between 2 different tab navigators after login and logout in react native screens of my app that all use function component screens
Can someone advice me on how to do this.
In my Navigation directory(which handle navigation flow), I have 2 files index.js and main.js
navigation/index.js
navigation/main.js
Once the user launches the app, the user sees screens in the navigation/index.js file.
After the user either signs up or signs in, the users see screens in the navigation/main.js file
I have implemented everything else in the app except navigate between navigators after login and logout in the app
I initially put all screens in the same navigator file but I started having issues after pressing the back button continuously
see the code below
:::::::::EDITS:::::::::::
No longer using Navigation/main.js
Now using only Navigation/index.js and implementing what was suggested by #Tolga Berk Ordanuç
Still need more help though because
It worked partially
Now
After logging in by clicking login I get the error
" ERROR The action 'NAVIGATE' with payload {"name":"BottomTabNavigator"} was not handled by any navigator.
Do you have a screen named 'BottomTabNavigator'?"
And when I close the app completely by hitting back numerous times,
I am logged in
But now second error, when I click logout
I get below error
ERROR The action 'NAVIGATE' with payload {"name":"Walkthrough"} was not handled by any navigator.
Do you have a screen named 'Walkthrough'?
home.js
import React, {useState} from 'react';
import {View} from 'react-native';
import {useTheme} from '#config';
import {Header, Icon, Button} from '#components';
import {useDispatch} from 'react-redux';
export default function Home({navigation, route}) {
const {colors} = useTheme();
const dispatch = useDispatch();
const [loading, setLoading] = useState(false);
const logout = () => {
setLoading(true);
dispatch(setIsLoggedIn(false));
navigation.navigate('SignIn');
setLoading(false);
};
return (
<View style={{flex: 1}}>
<Header
title="sign in"
renderLeft={() => {
return (
<Icon
name="times"
size={20}
color={colors.primary}
enableRTL={true}
/>
);
}}
onPressLeft={() => {
navigation.goBack();
}}
/>
<View>
<Button style={{marginTop: 20}} full loading={loading} onPress={logout}>
Log Out
</Button>
</View>
</View>
);
}
Navigation/main.js
import React from 'react';
import {createStackNavigator} from '#react-navigation/stack';
import {useTheme} from '#config';
import {useSelector} from 'react-redux';
import {designSelect} from '#selectors';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import {BaseColor, useFont} from '#config';
import {Icon} from '#components';
/* Main Stack Navigator */
/* Modal Screen only affect iOS */
import Savings from 'Savings';
import Loans from 'Loans';
import Home from 'Home';
import Profile from 'Profile';
/* Stack Screen */
import Setting from 'Setting';
import Feedback from 'Feedback';
import ChangePassword from 'ChangePassword';
import ProfileEdit from 'ProfileEdit';
import ContactUs from 'ContactUs';
import AboutUs from 'AboutUs';
import Support from 'Support';
const MainStack = createStackNavigator();
export default function Main() {
return (
<MainStack.Navigator
screenOptions={{
headerShown: false,
}}
initialRouteName="BottomTabNavigator">
<MainStack.Screen
name="BottomTabNavigator"
component={BottomTabNavigator}
/>
<MainStack.Screen name="Support" component={Support} />
<MainStack.Screen name="SavingsTemp" component={Savings} />
<MainStack.Screen
name="BottomTabNavigator"
component={BottomTabNavigator}
/>
<MainStack.Screen name="Setting" component={Setting} />
<MainStack.Screen name="Feedback" component={Feedback} />
<MainStack.Screen name="ChangePassword" component={ChangePassword} />
<MainStack.Screen name="ProfileEdit" component={ProfileEdit} />
<MainStack.Screen name="ContactUs" component={ContactUs} />
<MainStack.Screen name="AboutUs" component={AboutUs} />
</MainStack.Navigator>
);
}
function BottomTabNavigator() {
const {colors} = useTheme();
const font = useFont();
const BottomTab = createBottomTabNavigator();
const design = useSelector(designSelect);
/**
* Main follow return Home Screen design you are selected
* #param {*} design ['basic', 'real_estate','event', 'food']
* #returns
*/
const exportHome = () => {
return Home;
};
return (
<BottomTab.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: false,
}}
tabBarOptions={{
showIcon: true,
showLabel: true,
activeTintColor: colors.primary,
inactiveTintColor: BaseColor.grayColor,
style: {borderTopWidth: 1},
labelStyle: {
fontSize: 12,
fontFamily: font,
paddingBottom: 4,
},
}}>
<BottomTab.Screen
name="Home"
component={exportHome(design)}
options={{
title: 'home',
tabBarIcon: ({color}) => {
return <Icon color={color} name="home" size={20} solid />;
},
}}
/>
<BottomTab.Screen
name="Savings"
component={Savings}
options={{
title: 'Savings',
tabBarIcon: ({color}) => {
return <Icon color={color} name="bookmark" size={20} solid />;
},
}}
/>
<BottomTab.Screen
name="Loans"
component={Loans}
options={{
title: 'Loans',
tabBarIcon: ({color}) => {
return <Icon color={color} name="clipboard-list" size={20} solid />;
},
}}
/>
<BottomTab.Screen
name="Profile"
component={Profile}
options={{
title: 'Profile',
tabBarIcon: ({color}) => {
return <Icon solid color={color} name="user-circle" size={20} />;
},
}}
/>
</BottomTab.Navigator>
);
}
Navigation/index.js
import React, {useEffect, useState} from 'react';
import {StatusBar, Platform} from 'react-native';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import {DarkModeProvider, useDarkMode} from 'react-native-dark-mode';
import {useTheme, BaseSetting} from '#config';
import i18n from 'i18next';
import {initReactI18next} from 'react-i18next';
import {useSelector} from 'react-redux';
import {languageSelect, designSelect} from '#selectors';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import {BaseColor, useFont} from '#config';
import {useTranslation} from 'react-i18next';
import {Icon} from '#components';
/* Main Stack Navigator */
/* Modal Screen only affect iOS */
import Loading from 'Loading';
import SignIn from 'SignIn';
import SignUp from 'SignUp';
import ResetPassword from 'ResetPassword';
import Walkthrough from 'Walkthrough';
import Home from 'Home';
import Profile from 'Profile';
import Feedback from 'Feedback';
import ChangePassword from 'ChangePassword';
import ProfileEdit from 'ProfileEdit';
import ContactUs from 'ContactUs';
import AboutUs from 'AboutUs';
import Tab2 from 'Tab2';
import Tab3 from 'Tab3';
import BottomTabNavigator from './BottomTabNavigator';
import {store} from '../store';
const RootStack = createStackNavigator();
export default function Navigator() {
const language = useSelector(languageSelect);
const {theme, colors} = useTheme();
const isDarkMode = useDarkMode();
const [isLoggedInValue, setIsLoggedInValue] = useState(false);
useEffect(() => {
i18n.use(initReactI18next).init({
resources: BaseSetting.resourcesLanguage,
lng: language ?? BaseSetting.defaultLanguage,
fallbackLng: BaseSetting.defaultLanguage,
});
if (Platform.OS === 'android') {
StatusBar.setBackgroundColor(colors.primary, true);
}
StatusBar.setBarStyle(isDarkMode ? 'light-content' : 'dark-content', true);
console.log('<<<<< IS LOGGED IN STATE >>>>>>');
console.log(isLoggedInValue);
console.log('<<<<< IS LOGGED IN STATE >>>>>>');
setIsLoggedInValue(store.getState().isloggedin.isLoggedIn);
}, [colors.primary, isDarkMode, language, isLoggedInValue]);
return (
<DarkModeProvider>
<NavigationContainer theme={theme}>
<RootStack.Navigator
mode="modal"
screenOptions={{
headerShown: false,
}}>
{!isLoggedInValue ? (
<>
<RootStack.Screen
name="Loading"
component={Loading}
options={{gestureEnabled: false}}
/>
<RootStack.Screen name="Walkthrough" component={Walkthrough} />
<RootStack.Screen name="SignIn" component={SignIn} />
<RootStack.Screen name="SignUp" component={SignUp} />
<RootStack.Screen
name="ResetPassword"
component={ResetPassword}
/>
</>
) : (
<>
<RootStack.Screen
name="BottomTabNavigator"
component={BottomTabNavigator}
/>
<RootStack.Screen name="Feedback" component={Feedback} />
<RootStack.Screen
name="ChangePassword"
component={ChangePassword}
/>
<RootStack.Screen name="ProfileEdit" component={ProfileEdit} />
<RootStack.Screen name="ContactUs" component={ContactUs} />
<RootStack.Screen name="AboutUs" component={AboutUs} />
</>
)}
</RootStack.Navigator>
</NavigationContainer>
</DarkModeProvider>
);
}
Signin.js
import React, {useState} from 'react';
import {
View,
TouchableOpacity,
KeyboardAvoidingView,
Platform,
Alert,
} from 'react-native';
import {useDispatch} from 'react-redux';
import {BaseStyle, useTheme} from '#config';
import {Header, SafeAreaView, Icon, Text, Button, TextInput} from '#components';
import styles from './styles';
export default function SignIn({navigation, route}) {
const {colors} = useTheme();
const [loading, setLoading] = useState(false);
const [id, setId] = useState('');
const [password, setPassword] = useState('');
const dispatch = useDispatch();
/**
* call when action onLogin
*/
const onLogin = () => {
setLoading(true);
dispatch(setIsLoggedIn(true));
navigation.navigate('Home');
setLoading(false);
};
const offsetKeyboard = Platform.select({
ios: 0,
android: 20,
});
return (
<View style={{flex: 1}}>
<Header
title="sign in"
renderLeft={() => {
return (
<Icon
name="times"
size={20}
color={colors.primary}
enableRTL={true}
/>
);
}}
onPressLeft={() => {
navigation.goBack();
}}
/>
<SafeAreaView style={BaseStyle.safeAreaView} edges={['right', 'left']}>
<KeyboardAvoidingView
behavior={Platform.OS === 'android' ? 'height' : 'padding'}
keyboardVerticalOffset={offsetKeyboard}
style={{flex: 1}}>
<View style={styles.contain}>
<TextInput onChangeText={setId} placeholder="username" value={id} />
<TextInput
style={{marginTop: 10}}
onChangeText={setPassword}
placeholder="Password"
secureTextEntry={true}
value={password}
/>
<Button
style={{marginTop: 20}}
full
loading={loading}
onPress={onLogin}>
'sign_in'
</Button>
<TouchableOpacity
onPress={() => navigation.navigate('ResetPassword')}>
<Text body1 grayColor style={{marginTop: 25}}>
'forgot_your_password'
</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
</View>
);
}
5
navigation/BottomTabNavigator.js
export default function BottomTabNavigator() {
const {colors} = useTheme();
const font = useFont();
const design = useSelector(designSelect);
const BottomTab = createBottomTabNavigator();
const exportHome = () => {
return Home;
};
return (
<BottomTab.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: false,
}}
tabBarOptions={{
showIcon: true,
showLabel: true,
activeTintColor: colors.primary,
inactiveTintColor: BaseColor.grayColor,
style: {borderTopWidth: 1},
labelStyle: {
fontSize: 12,
fontFamily: font,
paddingBottom: 4,
},
}}>
<BottomTab.Screen
name="Home"
component={exportHome(design)}
options={{
title: 'Home',
tabBarIcon: ({color}) => {
return <Icon color={color} name="home" size={20} solid />;
},
}}
/>
<BottomTab.Screen
name="Savings"
component={Tab2}
options={{
title: 'Savings',
tabBarIcon: ({color}) => {
return <Icon color={color} name="bookmark" size={20} solid />;
},
}}
/>
<BottomTab.Screen
name="Loans"
component={Tab3}
options={{
title: 'Loans',
tabBarIcon: ({color}) => {
return <Icon color={color} name="clipboard-list" size={20} solid />;
},
}}
/>
<BottomTab.Screen
name="Profile"
component={Profile}
options={{
title: 'Profile',
tabBarIcon: ({color}) => {
return <Icon solid color={color} name="user-circle" size={20} />;
},
}}
/>
</BottomTab.Navigator>
);
}
I couldn't see the second tab navigator in your code but i saw that you create navigators inside a component which is in my opinion and experience is not what you supposed to do. you should create your navigators seperately not inside another component. in the documentation of react-navigation they show it this way so they should know what they are doing i guess :D
Login and Main app screens used to managed by switch navigators but with react-navigation 5 they dumped the switch navigators and instead support ternary operators in the navigator components like this
const RootStack = createStackNavigator<RootStackParamList>();
export const RootNavigator = () => {
const isLoggedIn = useReduxSelector(({ authState }) => authState.isLoggedIn);
return (
<RootStack.Navigator screenOptions={{ headerShown: false }}>
{!isLoggedIn ? (
<RootStack.Screen
name="AuthNavigator"
options={{ headerShown: false }}
component={AuthNavigator}
/>
) : (
<>
<RootStack.Screen name="TabNavigator" component={TabNavigator} />
<RootStack.Screen
name="DetailsNavigator"
component={DetailsNavigator}
/>
<RootStack.Screen
name="UserStackNavigator"
component={UserStackNavigator}
/>
<RootStack.Screen name="Announcements" component={Announcements} />
<RootStack.Screen name="Read" component={Read} />
<RootStack.Screen
name="Search"
options={{
...TransitionPresets.FadeFromBottomAndroid,
gestureEnabled: false,
}}
component={Search}
/>
</>
)}
</RootStack.Navigator>
);
};
After logging in and dispatching the appropriate action for your redux to change isLoggedIn state Navigator automatically strips out the Login page and fallbacks to what is under it. and at this point user cannot go to login or register screens even if they go back as many times as they want because we ripped the screens out of the navigation tree.
If you want to return to Login screens you just log out the user and navigation tree again contains these screens and you can navigate to them by navigation.navigate function with respective keys of your screens.
And also if you're curious what my tab navigator looks like it's just like this
const Tab = createBottomTabNavigator<TabParamList>();
//
const tabNavigatorScreenOptions: (props: {
route: RouteProp<TabParamList, keyof TabParamList>;
navigation: unknown;
}) => BottomTabNavigationOptions = ({ route }) => ({
tabBarIcon: (params) => <TabBarIcon {...params} route={route} />,
tabBarButton: (props) => (
<Pressable
{...props}
style={[props.style, { marginTop: Layout.dimensions.xs_h }]}
/>
),
// tabBarLabel: (props) => <TabBarLabel {...props} route={route} />,
});
export const TabNavigator = () => {
const debug = useReduxSelector(({ info }) => info.debug);
// Logger.debug = debug;
return (
<Tab.Navigator
tabBarOptions={{ adaptive: true, showLabel: false }}
screenOptions={tabNavigatorScreenOptions}
>
<Tab.Screen name="Discover" component={Discover} />
<Tab.Screen name="Library" component={LibraryNavigator} />
<Tab.Screen name="Settings" component={SettingsNavigator} />
{debug && <Tab.Screen name="TestNavigator" component={TestNavigator} />}
</Tab.Navigator>
);
};
Code is in typescript but that shouldn't be a problem about the logic.
if you have any questions further i am happy to help!
Happy coding my fellow react-native developer!

How to open a modal in drawer headerRight icon button?

I am new to react native and working on a dummy project. I use the react-navigation to set the header and headerRight and place a icon in the right side of the header. Now i want to open a modal whenever user click the icon it will show a modal. I tried many things but didn't find any proper solution. Now i am stuck and post this question. I am placing my code below.
Here is my Code:
//Navigation of my app
import * as React from "react";
import { View, TouchableOpacity, StyleSheet } from "react-native";
import { AntDesign, Fontisto } from "#expo/vector-icons";
import { createDrawerNavigator } from "#react-navigation/drawer";
import { createStackNavigator } from "#react-navigation/stack";
import AccountsScreen from "../screens/AccountsScreen";
import FavouritesScreen from "../screens/FavouritesScreen";
import HomeScreen from "../screens/HomeScreen";
import SettingsScreen from "../screens/SettingsScreen";
import TrendsScreen from "../screens/TrendsScreen";
import { createMaterialTopTabNavigator } from "#react-navigation/material-top-tabs";
import { Dimensions } from "react-native";
import Income from "../screens/Income";
import Expense from "../screens/Expense";
import FundTransferModal from "../components/Accounts/FundTransferModal";
const AppStack = () => {
return(
<Stack.Navigator mode="modal" headerMode="none">
<Stack.Screen name="Modal" component={FundTransferModal} />
</Stack.Navigator>
)
}
const AppDrawer = () => {
return (
<Drawer.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: true,
}}
>
<Drawer.Screen
name="Home"
component={HomeScreen}
options={{
headerRight: () => {
return (
<TouchableOpacity onPress={() => AppStack() }>
<View style={styles.icons}>
<AntDesign name="piechart" size={30} color="#29416F" />
</View>
</TouchableOpacity>
);
},
}}
/>
<Drawer.Screen name="Accounts" component={AccountsScreen} options={{
headerRight: () => {
return (
<TouchableOpacity>
<View style={styles.icons}>
<Fontisto name="arrow-swap" size={24} color="#29416F" onPress={() =>{return <FundTransferModal />}} />
</View>
</TouchableOpacity>
);
},
}} />
<Drawer.Screen name="Categories" component={CategoriesTabScreens} />
<Drawer.Screen name="Trends" component={TrendsScreen} />
<Drawer.Screen name="Favourites" component={FavouritesScreen} />
<Drawer.Screen name="Settings" component={SettingsScreen} />
</Drawer.Navigator>
);
};
export default AppDrawer;
const styles = StyleSheet.create({
icons:{
marginRight:20,
}
})
//The Modal which i want to open
import React, { Fragment, useState } from "react";
import { globalStyles } from "../../style/Global";
import { AntDesign, Entypo } from "#expo/vector-icons";
import { MaterialCommunityIcons } from "#expo/vector-icons";
import { Formik } from "formik";
import * as yup from "yup";
import { Picker } from "#react-native-picker/picker";
import SubmitButton from "../SubmitButton";
import { ExampleUncontrolledVertical } from "../../assets/ExampleUncontrolledVertical";
import {
Modal,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View,
Button,
Keyboard,
ScrollView,
} from "react-native";
import DatePiker from "../DatePikers";
export default function FundTransferModal({navigation}) {
const [fundModal, setFundModal] = useState(true);
const [selectedValue, setValue] = useState(0);
showFundModal = () => {
setFundModal(true);
};
closeFundModal = () => {
setFundModal(false);
};
const validations = yup.object({
text: yup.string().required().min(3),
});
const values = ["Cash", "Bank", "Other"];
const valuesTwo = ["Cash", "Bank", "Other"]
const initialValues = { value: "", valueTwo: "" };
return (
<Modal visible={fundModal} animationType="fade">
<View style={globalStyles.modalHeader}>
<AntDesign
name="arrowleft"
size={30}
onPress={() => closeFundModal()}
/>
<Text style={styles.headerText}>Transfer</Text>
</View>
<Formik
validationSchema={validations}
initialValues={{ amount: "" , notes:"" }}
onSubmit={(values, actions) => {
actions.resetForm();
console.log(values);
}}
>
{(props) => (
<Fragment>
<ScrollView>
<View style={styles.container}>
<View style={styles.box}>
<View style={styles.picker}>
<Picker
mode="dropdown"
selectedValue={props.values.value}
onValueChange={(itemValue) => {
props.setFieldValue("value", itemValue);
setValue(itemValue);
}}
>
<Picker.Item
label="Account"
value={initialValues.value}
key={0}
color="#afb8bb"
/>
{values.map((value, index) => (
<Picker.Item label={value} value={value} key={index} />
))}
</Picker>
</View>
<View style={styles.inputValue}>
<TextInput
style={styles.inputName}
placeholder="Value"
keyboardType="numeric"
onChangeText={props.handleChange("amount")}
value={props.values.amount}
onBlur={props.handleBlur("amount")}
/>
</View>
</View>
<View style={styles.doubleArrow}>
<Entypo name="arrow-long-down" size={40} color="#afb8bb" />
<Entypo name="arrow-long-down" size={40} color="#afb8bb" />
</View>
<View style={styles.box}>
<View style={styles.picker}>
<Picker
mode="dropdown"
selectedValue={props.values.valueTwo}
onValueChange={(itemValue) => {
props.setFieldValue("valueTwo", itemValue);
setValue(itemValue);
}}
>
<Picker.Item
label="Account"
value={initialValues.valueTwo}
key={0}
color="#afb8bb"
/>
{valuesTwo.map((value, index) => (
<Picker.Item label={value} value={value} key={index} />
))}
</Picker>
</View>
<View style={styles.Calendar}><DatePiker /></View>
<View style={styles.inputValue}>
<TextInput
style={styles.inputName}
placeholder="Notes"
multiline= {true}
onChangeText={props.handleChange("notes")}
value={props.values.notes}
onBlur={props.handleBlur("notes")}
/>
</View>
</View>
<SubmitButton title="Save" onPress={props.handleSubmit} />
</View>
</ScrollView>
</Fragment>
)}
</Formik>
</Modal>
);
}
const styles = StyleSheet.create({
headerText: {
fontSize: 20,
marginLeft: 5,
},
container: {
flex: 1,
},
box: {
borderColor: "#afb8bb",
margin: 20,
flexDirection: "column",
borderWidth: 1,
borderStyle: "dashed",
borderRadius:5,
marginTop:40,
},
inputName:{
padding:10,
borderWidth:1,
borderColor:"#afb8bb",
},
inputValue:{
margin:10,
marginHorizontal:20,
},
picker:{
borderWidth:1,
borderColor:"#afb8bb",
margin:10,
marginHorizontal:20,
},
doubleArrow:{
flexDirection:'row',
alignContent:'center',
justifyContent:'center',
marginTop:10
},
Calendar: {
marginTop:-20,
borderColor: "#afb8bb",
paddingVertical: 10,
marginHorizontal:20,
fontSize: 20,
textAlign: 'center',
color: 'black',
}
});

Why is React Native App.js navigation undefined in App.js?

export default function App ({navigation})
There is a function that starts with and contains <Stack.Navigator>.
But when I want to use the navigation feature and use "navigation.navigate ('Lead') in onPress
TypeError: undefined is not an object evaluating react navigation
I get an error. My English is not very good. Please help me on this topic. Now I'm adding the sample codes to you.
import * as React from 'react';
import { StyleSheet, AsyncStorage, Alert, View, Image, TouchableOpacity } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { ApplicationProvider, Layout, Input, Button, Text, Spinner, IconRegistry, Icon } from '#ui-kitten/components';
import { EvaIconsPack } from '#ui-kitten/eva-icons';
import * as eva from '#eva-design/eva';
import LinkingConfiguration from './navigation/LinkingConfiguration';
import * as axios from 'axios';
import Base64 from './components/Base64';
import LeadScreen from './screens/LeadScreen';
import AddLeadScreen from './screens/AddLeadScreen';
import TabBarIcon from './components/TabBarIcon';
import HomeScreen from './screens/HomeScreen';
import CampaignsScreen from './screens/CampaignsScreen';
import MenuScreen from './screens/MenuScreen';
const Stack = createStackNavigator();
export default function App({ navigation }) {
const logout = async () => {
await AsyncStorage.removeItem('token');
dispatch({ type: 'SIGN_OUT' });
};
return (
<>
<IconRegistry icons={EvaIconsPack} />
<ApplicationProvider {...eva} theme={eva.light}>
<Layout style={styles.container}>
<AuthContext.Provider value={authContext}>
<NavigationContainer linking={LinkingConfiguration}>
<Stack.Navigator>
{state.isLoading ? (
// We haven't finished checking for the token yet
<Stack.Screen name="Splash" component={SplashScreen} options={{ headerShown: false }} />
) : state.token == null ? (
// No token found, user isn't signed in
<>
<Stack.Screen name="Login" component={LoginScreen} options={{ title: 'Oturum Açın' }} />
</>
) : (
// User is signed in
<>
<Stack.Screen name="User" component={UserScreen} options={{
headerStyle: { backgroundColor: '#e8a200' },
headerTintColor: 'white',
headerTitleStyle: { color: '#fff' },
headerRight: () => (
<TouchableOpacity activeOpacity={0.4} underlayColor='transparent' onPress={() => logout() } style={{ marginRight: 12 }}>
<Icon
style={styles.icon}
fill='#FFFFFF'
name='power-outline'
/>
</TouchableOpacity>
)
}} />
<Stack.Screen name="Lead" component={LeadScreen} options={{
title: 'Müşteri Adayları',
headerStyle: { backgroundColor: '#e8a200' },
headerTintColor: 'white',
headerTitleStyle: { fontWeight: 'bold', color: '#fff' },
headerRight: () => (
<TouchableOpacity activeOpacity={0.4} underlayColor='transparent' onPress={ () => console.log(navigation) } style={{ marginRight: 12 }}>
<Icon
style={styles.icon}
fill='#FFFFFF'
name='plus-outline'
/>
</TouchableOpacity>
)}} />
<Stack.Screen name="AddLead" component={AddLeadScreen} options={{ title: 'Müşteri Adayı Ekle' }} />
</>
)}
</Stack.Navigator>
</NavigationContainer>
</AuthContext.Provider>
</Layout>
</ApplicationProvider>
</>
);
}
You can pass the navigation or rout prop into options in the stack.screen like this
options={({navigation})=>({
'Your code here'
})}
I have edited it with your code for you.
<Stack.Screen name="Lead" component={LeadScreen}
options={({ navigation }) => ({
title: 'Müşteri Adayları',
headerStyle: { backgroundColor: '#e8a200' },
headerTintColor: 'white',
headerTitleStyle: { fontWeight: 'bold', color: '#fff' },
headerRight: () => (
<TouchableOpacity activeOpacity={0.4}
underlayColor='transparent' onPress={() =>
console.log(navigation)} style={{ marginRight: 12 }}>
<Icon
style={styles.icon}
fill='#FFFFFF'
name='plus-outline'
/>
</TouchableOpacity>
)
})} />
First, I think the navigation here is unnecessary, you can remove it.
export default function App({ navigation }) {
In your screen components, ie. UserScreen, you can use navigation like so
function UserScreen({navigation}) {
// ...some codes
navigation.navigate('WHERE_TO_GO');
// ...some other codes
}
You could also use navigation without passing it to the props.
First you need to import useNavigation
import { useNavigation } from '#'react-navigation/native'
And then, in your component
function UserScreen() {
const nav = useNavigation();
// ...some codes
nav.navigate('WHERE_TO_GO');
// ...some other codes
}
You could get more details here https://reactnavigation.org/docs/use-navigation/
For the onPress function of Lead screen,
<Stack.Screen name="Lead" component={LeadScreen} options={({ navigation }) => ({
title: 'Müşteri Adayları',
headerStyle: { backgroundColor: '#e8a200' },
headerTintColor: 'white',
headerTitleStyle: { fontWeight: 'bold', color: '#fff' },
headerRight: () => (
<TouchableOpacity activeOpacity={0.4} underlayColor='transparent' onPress={ () => navigation.navigate('WHERE_TO_GO') } style={{ marginRight: 12 }}>
<Icon
style={styles.icon}
fill='#FFFFFF'
name='plus-outline'
/>
</TouchableOpacity>
)})} />
You should use useLinkProps to solve this issue:
import { useLinkProps } from '#react-navigation/stack';
And this is an example on how to write code which uses it:
const LinkButton = ({ to, action, children, ...rest }) => {
const { onPress, ...props } = useLinkProps({ to, action });
I have tried everything but this worked for me.
Make a function in your app.js and pass props then access using props.navigation like below.
function CustomDrawerContent**(props)** {
.....
logOut = () => {
AsyncStorage.clear();
**props.navigation.navigate("Login");**
};
.....
}

Categories

Resources