I am trying to navigate from login screen to Tabs screen, But I am getting the following error
Undefined is not an object (evaluating
'this.props.navigation.navigate')
Below is my Login.js:
import React, {Component} from 'react';
import {Text, View, StyleSheet, ImageBackground, Image, TextInput} from 'react-native';
import { Button } from 'react-native-elements'
import firebase from 'firebase';
const textInputConfig = {
placeholderTextColor : '#838383',
}
export default class Login extends Component<{}>{
static navigationOptions = {
header: null
}
login() {
this.props.navigation.navigate('Tabs');
}
render (){
return (
<View style={styles.container}>
<ImageBackground source={require('../resources/images/background_image.png')} style={styles.backgroundImage} >
<Image source={require('../resources/images/app_logo.png')} style={styles.logo}/>
<View style={styles.formContainer}>
<TextInput style={styles.textInput} placeholder='Username'
placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<TextInput style={styles.textInput} placeholder='Email'
placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<TextInput style={styles.textInput} placeholder='Password'
secureTextEntry={true} placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<Button raised title='SIGN UP' buttonStyle={styles.signupButton}
containerViewStyle={styles.signupButtonContainer} onPress={() => this.login()} />
</View>
</ImageBackground>
</View>
);
}
}
.....
Below is my Router.js
import React from 'react';
import { TabNavigator, StackNavigator } from 'react-navigation';
import { Icon } from 'react-native-elements';
import Home from '../screens/Home';
import MyCards from '../screens/MyCards';
import AddCard from '../screens/AddCard';
import Login from '../screens/Login.js';
export const MainScreenNavigator = TabNavigator({
Home: {
screen: Home,
navigationOptions : {
tabBarLabel: 'Home',
tabBarIcon: ({ tintColor }) => <Icon name="account-circle" size={35} color={tintColor} />
},
},
MyCards: {
screen: MyCards,
navigationOptions : {
tabBarLabel: 'My Cards',
tabBarIcon: ({ tintColor }) => <Icon name="list" size={35} color={tintColor} />
},
},
},
{
tabBarPosition: 'bottom',
animationEnabled: true,
tabBarOptions: {
activeTintColor: '#e91e63',
},
},
);
export const AppNavigation = StackNavigator({
LoginScreen: { screen: Login },
Tabs: { screen: MainScreenNavigator},
AddCard: { screen: AddCard }
},
{
headerMode: 'screen'
});
Can someone please tell what I am doing wrong?
Edit Login.js:
import React, {Component} from 'react';
import {Text, View, StyleSheet, ImageBackground, Image, TextInput} from 'react-native';
import { Button } from 'react-native-elements'
import firebase from 'firebase';
const textInputConfig = {
placeholderTextColor : '#838383',
}
export default class Login extends Component<{}>{
static navigationOptions = {
header: null
}
login = () => {
console.log("login function");
this.props.navigation.navigate('Tabs');
}
render (){
return (
<View style={styles.container}>
<ImageBackground source={require('../resources/images/background_image.png')} style={styles.backgroundImage} >
<Image source={require('../resources/images/app_logo.png')} style={styles.logo}/>
<View style={styles.formContainer}>
<TextInput style={styles.textInput} placeholder='Username'
placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<TextInput style={styles.textInput} placeholder='Email'
placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<TextInput style={styles.textInput} placeholder='Password'
secureTextEntry={true} placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<Button raised title='SIGN UP' buttonStyle={styles.signupButton}
containerViewStyle={styles.signupButtonContainer} onPress={this.login} />
</View>
</ImageBackground>
</View>
);
}
}
It has the reference issue!
Replace onPress={() => this.login()} with onPress={this.login.bind(this)}
<Button raised title='SIGN UP' buttonStyle={styles.signupButton}
containerViewStyle={styles.signupButtonContainer} onPress={this.login.bind(this)} />
Related
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!
I am trying to navigate to another screen with in my album component when the user click
on a album but I keep getting this error
The action 'NAVIGATE' with payload {"name":"AlbumScreen"} was not handled by any navigator.
below is my code and my try
navigation->Album->index.tsx
import React from 'react';
import { View, Image, Text, TouchableWithoutFeedback } from 'react-native';
import styles from './style';
import { Album, TabOneParamList } from '../../types';
import { useNavigation } from '#react-navigation/native';
// import Navigation from '../navigation';
export type AlbumProps = {
album: Album,
}
const AlbumComponent = (props: AlbumProps) => {
const navigation = useNavigation();
const onPress = () => {
navigation.navigate('AlbumScreen');
}
return (
<TouchableWithoutFeedback onPress={onPress}>
<View style={styles.container}>
<Image source={{ uri: props.album.imageUri }} style={styles.image} />
<Text style={styles.text}>{props.album.artistsHeadline}</Text>
</View>
</TouchableWithoutFeedback>
);
}
export default AlbumComponent;
here is my AlbumScreen.tsx also this is the screen I want to user to move to once they click on the Album
import React from 'react';
import { View, Text } from 'react-native';
const AlbumScreen = () => (
<View>
<Text style={{ color: 'white' }} >Hello from Album Screen</Text>
</View>
);
export default AlbumScreen;
also here is my BottomTabNavigation which I add the newly created AlbumScreen just the way the HomeScreen is added
import {
Ionicons,
Entypo,
EvilIcons,
MaterialCommunityIcons,
FontAwesome5,
FontAwesome
} from '#expo/vector-icons';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createStackNavigator } from '#react-navigation/stack';
import * as React from 'react';
import Colors from '../constants/Colors';
import useColorScheme from '../hooks/useColorScheme';
import TabOneScreen from '../screens/HomeScreen';
import AlbumScreen from '../screens/AlbumScreen';
import TabTwoScreen from '../screens/TabTwoScreen';
import { BottomTabParamList, TabOneParamList, TabTwoParamList } from '../types';
const BottomTab = createBottomTabNavigator<BottomTabParamList>();
export default function BottomTabNavigator() {
const colorScheme = useColorScheme();
return (
<BottomTab.Navigator
initialRouteName="Home"
tabBarOptions={{ activeTintColor: Colors[colorScheme].tint }}>
<BottomTab.Screen
name="Home"
component={TabOneNavigator}
options={{
tabBarIcon: ({ color }) => <Entypo name="home" size={30} style={{ marginBottom: -3 }} color={color} />,
}}
/>
<BottomTab.Screen
name="store"
component={TabTwoNavigator}
options={{
tabBarIcon: ({ color }) => <MaterialCommunityIcons name="store" size={30} style={{ marginBottom: -3 }} color={color} />,
}}
/>
<BottomTab.Screen
name="Library"
component={TabTwoNavigator}
options={{
tabBarIcon: ({ color }) => <Ionicons name="library-outline" size={30} style={{ marginBottom: -3 }} color={color} />,
}}
/>
<BottomTab.Screen
name="Profile"
component={TabTwoNavigator}
options={{
tabBarIcon: ({ color }) => <FontAwesome name="user-circle" size={28} style={{ marginBottom: -3 }} color={color} />,
}}
/>
</BottomTab.Navigator>
);
}
// Each tab has its own navigation stack, you can read more about this pattern here:
// https://reactnavigation.org/docs/tab-based-navigation#a-stack-navigator-for-each-tab
const TabOneStack = createStackNavigator<TabOneParamList>();
function TabOneNavigator() {
return (
<TabOneStack.Navigator>
<TabOneStack.Screen
name="TabOneScreen"
component={TabOneScreen}
options={{ headerTitle: 'Home' }}
/>
<TabOneStack.Screen
name="AlbumScreen"
component={AlbumScreen}
options={{ headerTitle: 'Album' }}
/>
</TabOneStack.Navigator>
);
}
const TabTwoStack = createStackNavigator<TabTwoParamList>();
function TabTwoNavigator() {
return (
<TabTwoStack.Navigator>
<TabTwoStack.Screen
name="TabTwoScreen"
component={TabTwoScreen}
options={{ headerTitle: 'Tab Two Title' }}
/>
</TabTwoStack.Navigator>
);
}
Here is the picture of what I am trying to do I want upon clicking on the album on the right of this image the user is direct to another screen but I keep getting the Highlighted error my errors
You will need to specify which stack you are targeting when you attempt to navigate.
https://reactnavigation.org/docs/nesting-navigators/#navigating-to-a-screen-in-a-nested-navigator
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',
}
});
I am trying to navigate screens by pressing on specific images on SearchScreen.js. Each image leads to a different screen. I am currently trying to navigate from the first image to the screen meo_sw.js. However, I am not being able to do so and I don't undersand why. Here is the code of SearchScreen.js:
import React from 'react';
import { ScrollView, StyleSheet, TextInput, Text, View, Image, TouchableOpacity, TouchableWithoutFeedback} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
function SearchScreen() {
return (
<View style={styles.screen}>
<View style={styles.container}>
<TextInput style={styles.inputBox}
underlineColorAndroid='rgba(0,0,0,0)'
placeholder="Procura aqui"
placeholderTextColor = "black"
selectionColor="black"
keyboardType="default"/>
</View>
<View style={styles.teste}>
<Text style={styles.festivais}>Recomendados</Text>
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false} style={styles.festivais_lista}>
<TouchableOpacity onPress={() => navigate('meo_sw')}>
<Image source={require('../assets/images/meo_sudoeste.png')} style={styles.image}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate('vodaf_coura')}>
<Image source={require('../assets/images/vodafone_coura.png')} style={styles.image} />
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate('superR_superB')}>
<Image source={require('../assets/images/superbock_superrock.png')} style={styles.image}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate('nos_primavera')}>
<Image source={require('../assets/images/nos_primavera.png')} style={styles.image}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate('rock_in_rio')}>
<Image source={require('../assets/images/rock_in_rio.png')} style={styles.image}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate('edp_cool_jazz')}>
<Image source={require('../assets/images/edp_cooljazz.png')} style={styles.image}/>
</TouchableOpacity>
</ScrollView>
</View>
</View>
);
}
SearchScreen.navigationOptions = {
title: 'Procurar',
};
const styles = StyleSheet.create({
//I took this off because it's irrelevant for the question itself
});
export default SearchScreen;
And here is the screen 'meo_sw.js':
import React from 'react';
import {View, Text, TouchableOpacity, StyleSheet} from 'react-native';
const meo_sw = props => {
return(
<View style={styles.header}>
<Text style={styles.texto}>Meo Sudoeste</Text>
</View>
)
};
const styles=StyleSheet.create({
//Irrelevant
})
export default meo_sw;
The error says simply:
ReferenceError: Can't find variable: navigate
Please help me
UPDATED
This is the MainTabNavigator.js:
import React from 'react';
import { Platform } from 'react-native';
import { createStackNavigator } from 'react-navigation-stack';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import TabBarIcon from '../components/TabBarIcon';
import HomeScreen from '../screens/HomeScreen';
import SearchScreen from '../screens/SearchScreen';
import SettingsScreen from '../screens/SettingsScreen';
import ChatScreen from '../screens/ChatScreen';
import CalendarScreen from '../screens/CalendarScreen';
import meo_sw from '../Eventos/Festivais/meo_sw';
const config = Platform.select({
web: { headerMode: 'screen' },
default: {},
});
//Home
const HomeStack = createStackNavigator(
{
HomeScreen: {screen: HomeScreen},
SearchScreen: {screen: SearchScreen},
ChatScreen: {screen: ChatScreen},
SettingsScreen: {screen: SettingsScreen},
CalendarScreen: {screen: CalendarScreen},
},
config
);
HomeStack.navigationOptions = {
tabBarLabel: 'Home',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-home${focused ? '' : '-outline'}`
: 'md-home'
}
/>
),
};
HomeStack.path = '';
//Search
const SearchStack = createStackNavigator(
{
Search: SearchScreen,
},
config
);
SearchStack.navigationOptions = {
tabBarLabel: 'Procurar',
tabBarIcon: ({ focused }) => (
<TabBarIcon focused={focused} name={Platform.OS === 'ios' ? 'ios-search' : 'md-search'} />
),
};
SearchStack.path = '';
//Chat
const ChatStack = createStackNavigator(
{
Chat: ChatScreen,
},
config
);
ChatStack.navigationOptions = {
tabBarLabel: 'Chat',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-chatboxes${focused ? '' : '-outline'}`
: 'md-chatboxes'
}
/>
),
};
ChatStack.path = '';
//Settings
const SettingsStack = createStackNavigator(
{
Settings: SettingsScreen,
},
config
);
SettingsStack.navigationOptions = {
tabBarLabel: 'Perfil',
tabBarIcon: ({ focused }) => (
<TabBarIcon focused={focused} name={Platform.OS === 'ios' ? 'ios-person' : 'md-person'} />
),
};
SettingsStack.path = '';
//Calendar
const CalendarStack = createStackNavigator(
{
Calendar: CalendarScreen,
},
config
);
CalendarStack.navigationOptions = {
tabBarLabel: 'Calendário',
tabBarIcon: ({ focused }) => (
<TabBarIcon focused={focused} name={Platform.OS === 'ios' ? 'ios-calendar' : 'md-calendar'} />
),
};
CalendarStack.path = '';
//Bottom tab navigator
const tabNavigator = createBottomTabNavigator({
SearchStack,
CalendarStack,
HomeStack,
ChatStack,
SettingsStack
});
tabNavigator.path = '';
export default tabNavigator;
And this is the AppNavigator.js:
import React from 'react';
import { createAppContainer, createSwitchNavigator } from 'react-navigation';
import MainTabNavigator from './MainTabNavigator';
export default createAppContainer(
createSwitchNavigator({
Main: MainTabNavigator,
})
);
Pass navigation object as prop.
function SearchScreen({ navigation }) {
....
}
The use it like
<TouchableOpacity onPress={() => navigation.navigate('meo_sw')}>
<Image source={require('../assets/images/meo_sudoeste.png')} style={styles.image}/>
</TouchableOpacity>
Add the screen to one of your navigators, like the following.
const HomeStack = createStackNavigator(
{
HomeScreen: { screen: HomeScreen },
SearchScreen: { screen: SearchScreen },
ChatScreen: { screen: ChatScreen },
SettingsScreen: { screen: SettingsScreen },
CalendarScreen: { screen: CalendarScreen },
meo_sw: { screen: meo_sw}
},
config
);
HomeStack.navigationOptions = {
tabBarLabel: 'Home',
tabBarIcon: ({ focused }) => (
<TabBarIcon
focused={focused}
name={
Platform.OS === 'ios'
? `ios-home${focused ? '' : '-outline'}`
: 'md-home'
}
/>
),
};
Expo example
your Function is unable to get the props so that its not importing navigation property !!
change the function into class and get the props in class and then try navigating.
try this code
export default class SearchScreen extends Component {
constructor(props) {
super(props);
this.state = { }
}
return (
<View style={styles.screen}>
<View style={styles.container}>
<TextInput style={styles.inputBox}
underlineColorAndroid='rgba(0,0,0,0)'
placeholder="Procura aqui"
placeholderTextColor = "black"
selectionColor="black"
keyboardType="default"/>
</View>
<View style={styles.teste}>
<Text style={styles.festivais}>Recomendados</Text>
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false} style={styles.festivais_lista}>
<TouchableOpacity onPress={() => this.props.navigation.navigate('meo_sw')}>
<Image source={require('../assets/images/meo_sudoeste.png')} style={styles.image}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate('vodaf_coura')}>
<Image source={require('../assets/images/vodafone_coura.png')} style={styles.image} />
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate('superR_superB')}>
<Image source={require('../assets/images/superbock_superrock.png')} style={styles.image}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate('nos_primavera')}>
<Image source={require('../assets/images/nos_primavera.png')} style={styles.image}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate('rock_in_rio')}>
<Image source={require('../assets/images/rock_in_rio.png')} style={styles.image}/>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.navigation.navigate('edp_cool_jazz')}>
<Image source={require('../assets/images/edp_cooljazz.png')} style={styles.image}/>
</TouchableOpacity>
</ScrollView>
</View>
</View>
);
}
Hope it helps , feel free for doubts.
I am trying to navigate from login screen to home screen and below is the error I am getting.
Undefined is not an object evaluating
(_this.props.navigation.navigate())
Below is my login.js:
export default class Login extends Component<{}>{
static navigationOptions = {
header: null
}
login = () => {
alert('login');
this.props.navigation.navigate('Tabs');
}
render (){
return (
<View style={styles.container}>
<ImageBackground source={require('../resources/images/background_image.png')} style={styles.backgroundImage} >
<Image source={require('../resources/images/app_logo.png')} style={styles.logo}/>
<View style={styles.formContainer}>
<TextInput style={styles.textInput} placeholder='Username'
placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<TextInput style={styles.textInput} placeholder='Email'
placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<TextInput style={styles.textInput} placeholder='Password'
secureTextEntry={true} placeholderTextColor={textInputConfig.placeholderTextColor} autoCapitalize='none'/>
<Button raised title='SIGN UP' buttonStyle={styles.signupButton}
containerViewStyle={styles.signupButtonContainer} onPress={this.login} />
</View>
</ImageBackground>
</View>
);
}
}
----
Please note that the Login function is being called and even the alert is being displayed but still I am getting the error. Can anyone please tell whats wrong here?
Edit:
Router.js:
import React from 'react';
import { TabNavigator, StackNavigator } from 'react-navigation';
import { Icon } from 'react-native-elements';
import Home from '../screens/Home';
import MyCards from '../screens/MyCards';
import AddCard from '../screens/AddCard';
import Login from '../screens/Login.js';
export const MainScreenNavigator = TabNavigator({
Home: {
screen: Home,
navigationOptions : {
tabBarLabel: 'Home',
tabBarIcon: ({ tintColor }) => <Icon name="account-circle" size={35} color={tintColor} />
},
},
MyCards: {
screen: MyCards,
navigationOptions : {
tabBarLabel: 'My Cards',
tabBarIcon: ({ tintColor }) => <Icon name="list" size={35} color={tintColor} />
},
},
},
{
tabBarPosition: 'bottom',
animationEnabled: true,
tabBarOptions: {
activeTintColor: '#e91e63',
},
},
);
export const AppNavigation = StackNavigator({
LoginScreen: { screen: Login },
Tabs: { screen: MainScreenNavigator},
AddCard: { screen: AddCard }
},
{
headerMode: 'screen'
});