I'm learning React Native and by trying to run this code using Expo it gives me the Exception error:
undefined is not an object (evaluating 'props.navigation.navigate'), at line 17 on App.js (marked in the comment)
There are two files: App.js and Untitled1.js
App:
import { StyleSheet, Text, View, TextInput, TouchableOpacity } from 'react-native';
import 'react-native-gesture-handler';
import { NavigationContainer } from '#react-navigation/native';
function App(props) {
return (
<View style={styles.container}>
<Text style={styles.logo}>APPetito</Text>
<Text style={styles.loginText}>Welcome to our app!</Text>
<Text style={styles.loginText}>Choose what do you want to do</Text>
// [ THE FOLLOWING LINE CONTAINS THE ERROR ]
<TouchableOpacity onPress={() => props.navigation.navigate("Untitled1")} style={styles.loginBtn}>
<Text style={styles.loginText}>I eat food</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.loginBtn}>
<Text style={styles.loginText}>I sell food</Text>
</TouchableOpacity>
</View>
);
}
// here there are the const styles
export default App;
Untitled.js
import * as React from 'react';
import React, { Component } from "react";
import { StyleSheet, View, Text } from "react-native";
import Icon from "react-native-vector-icons/Entypo";
import { NavigationContainer } from '#react-navigation/native';
function Untitled1(props) {
return (
<View style={styles.container}>
<Icon name="check" style={styles.icon}></Icon>
<Text style={styles.itWorks}>It works!</Text>
</View>
);
}
// here there are the const styles
export default Untitled1;
What can I do to solve the problem?
I think the problem is that you didn't create a Stack navigator in the first place to navigate between screens. Refer to react navigation docs to know more here
According to the docs you have to implement the stack navigator such as:
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
function Home(props) {
return (
<View style={styles.container}>
<Text style={styles.logo}>APPetito</Text>
<Text style={styles.loginText}>Welcome to our app!</Text>
<Text style={styles.loginText}>Choose what do you want to do</Text>
<TouchableOpacity onPress={() => props.navigation.navigate("Untitled1")} style={styles.loginBtn}>
<Text style={styles.loginText}>I eat food</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.loginBtn}>
<Text style={styles.loginText}>I sell food</Text>
</TouchableOpacity>
</View>
);
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Untitled1" component={Untitled1} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
I have updated your code a little bit to help you understand the concept.
Related
Here's a Stack Navigator inside a MainStack.js:
import React from 'react'
import { createStackNavigator } from '#react-navigation/stack';
import Main from './Main'
import ScannerMarker from './ScannerMarker';
const Stack = createStackNavigator();
export default function MainStack() {
return(
<Stack.Navigator initialRouteName='Main' screenOptions={{headerShown: false}}>
<Stack.Screen name='Main' component={Main} />
<Stack.Screen name='ScannerMarker' component={ScannerMarker} />
</Stack.Navigator>
);
}
And ScannerMarker.js:
import React from 'react';
import { StyleSheet, View, Text, Dimensions, Pressable } from 'react-native';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import Feather from 'react-native-vector-icons/Feather';
import Octicon from 'react-native-vector-icons/Octicons'
import Main from './Main';
export default function ScannerMarker({ navigation, setModalVisible }) {
return (
<View style={styles.markerContainer}>
<View style={styles.topContainer}>
<View style={styles.topBar}>
<MaterialIcon name="support-agent" size={32} color="#fffeef" backgroundColor={'none'} onPress={() => navigation.navigate(Main)} />
<Feather name="x" size={32} color="#fffeef" backgroundColor={'none'} onPress={() => navigation.goBack(Support)}/>
</View>
<Text style={styles.topText}>Point scanner to{'\n'}vending qr-code</Text>
</View>
<View style={styles.middleContainer}>
<View style={styles.leftContainer}></View>
<View style={styles.scannerSquare}></View>
<View style={styles.rightContainer}></View>
</View>
<View style={styles.bottomContainer}>
<Pressable style={styles.button} onPress={() => setModalVisible(false)}>
<Octicon name="number" size={20} color="#fffeef" style={styles.chargerIcon}/>
<Text style={styles.buttonText}> Enter vending{'\n'}number</Text>
</Pressable>
</View>
</View>
)
}
ScannerMarker is a part of a Scanner in Scanner.js:
import React from 'react';
import { StyleSheet, Linking, Dimensions} from 'react-native';
import QRCodeScanner from 'react-native-qrcode-scanner';
import { RNCamera } from 'react-native-camera';
import ScannerMarker from './ScannerMarker';
export default function Scanner({ modalVisible, setModalVisible }) {
onSuccess = e => {
Linking.openURL(e.data)
setModalVisible(!modalVisible)
};
return (
<QRCodeScanner
onRead={this.onSuccess}
flashMode={RNCamera.Constants.FlashMode.auto}
cameraStyle={styles.cameraStyle}
showMarker={true}
customMarker={
<ScannerMarker setModalVisible={setModalVisible}> </ScannerMarker>
}
/>
);
}
MainStack is rendered inside a Drawer Navigator in Drawer.js:
import React from 'react';
import { StyleSheet, View, Linking} from 'react-native';
import { createDrawerNavigator, DrawerItemList, DrawerContentScrollView, DrawerItem} from '#react-navigation/drawer';
import MaterialCommunityIcon from 'react-native-vector-icons/MaterialCommunityIcons';
const Drawer = createDrawerNavigator();
export default function MyDrawer(props) {
return (
<Drawer.Navigator
...
>
<Drawer.Screen
name='MainStack'
component={MainStack}
options={{
title: 'Charge Away',
drawerIcon: () => (<MaterialCommunityIcon name="lightning-bolt" size={45} color="#2E2A00" style={{marginEnd: -30, marginStart: -10}} />)
}}
/>
...
<Drawer.Navigator>
);
}
When i press on icons with "onPress={() => navigation.navigate(...)}" or onPress={() => navigation.goBack()} I get the following errors:
TypeError: Cannot read property 'navigate' of undefined and TypeError: Cannot read property 'goBack' of undefined
So I don't know what's the problem. navigation parametr is declared and all of the components are in the Stack Navigator.
Everything is wrapped in NavigationContainer in App.js:
import * as React from 'react';
import { NavigationContainer} from '#react-navigation/native';
import MyDrawer from './components/Drawer'
export default function App() {
return (
<NavigationContainer>
<MyDrawer />
</NavigationContainer>
);
}
I've solved the problem using useNavigation function:
import { View, Button } from 'react-native';
import { useNavigation } from '#react-navigation/native';
export default function MyComp() {
const navigation = useNavigation();
return (
<View>
<Button
title="Go to Home"
onPress={() => navigation.navigate('Home')}
/>
</View>
);
};
Another option is to pass navigation to MyComp with props:
export default function MyComp( {navigation} ) {
//...
};
<MyComp navigation={props.navigation} />
Source:
https://reactnavigation.org/docs/connecting-navigation-prop
I'm trying to work with React Navigation using an external button component, to make styling it easier, but it gives me the TypeError: undefined is not an object (evaluating '_this.props.navigation') error when I try to pass the navigation. If I create the button on my home screen it works fine, but that clutters up my HomeScreen's stylesheet, and means I have to repeat code when I use the button elsewhere.
I have the stack navigation set up in my App.js, and again, it works fine when I'm not trying to pass the navigation as a prop.
Here's HomeScreen.js
import React from "react";
import {
ScrollView,
StyleSheet,
Text,
View,
AsyncStorage,
} from 'react-native';
import Heading from '../heading';
import Input from '../Input';
import Button from "../Button";
export const Home = ({navigation}) => (
<View style={styles.container}>
<ScrollView style={styles.content}>
<Heading />
</ScrollView>
<Button/>
</View>
)
And here's my Button.js
/* eslint-disable prettier/prettier */
import React from 'react';
import {
StyleSheet,
Text,
View,
TouchableHighlight
} from 'react-native';
import { useNavigation } from '#react-navigation/native';
function Button(){
const navigation = useNavigation()
return(
<View style={styles.buttonContainer}>
<TouchableHighlight
underlayColor='rgba(175, 47, 47, .75)'
activeOpacity={1.0}
style={styles.button}
onPress={() => {
navigation.navigate("New Medication");
}}>
<Text style={styles.submit}>
+
</Text>
</TouchableHighlight>
</View>
)
}
As far as I understand it, this should work just fine, so why is it saying that it's being passed as undefined?
UPDATE: Thanks to some suggestions I now have it to where it doesn't give an error, just does nothing.
Here's my App.js, with my navigation
const Stack = createStackNavigator();
function MyStack() {
return (
<Stack.Navigator
screenOptions={{
headerShown: false
}}>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="NewMedication" component={newMedScreen} />
</Stack.Navigator>
);
}
class App extends Component{
render(){
return(
<NavigationContainer>
<MyStack />
</NavigationContainer>
);
}
}
export default App;
I recommend you to create a const with screen name and reuse it everywhere to avoid such problem. You nave stack like this <Stack.Screen name="NewMedication" component={newMedScreen} /> , but try to navigate
navigation.navigate("New Medication").Of course this screen do not exist
const NEW_MEDICATION_SCREEN = 'NewMedication'
<Stack.Screen name={NEW_MEDICATION_SCREEN} component={newMedScreen} />
.....
onPress={() => navigation.navigate(NEW_MEDICATION_SCREEN)}>
and for make Button reusable use it like this
function Button({onPress}){
return(
<View style={styles.buttonContainer}>
<TouchableHighlight
underlayColor='rgba(175, 47, 47, .75)'
activeOpacity={1.0}
style={styles.button}
onPress={onPress}>
<Text style={styles.submit}>
+
</Text>
</TouchableHighlight>
</View>
)}
export const Home = ({navigation}) => (
<View style={styles.container}>
<ScrollView style={styles.content}>
<Heading />
</ScrollView>
<Button onPress={() => navigation.navigate(NEW_MEDICATION_SCREEN)}/>
</View>
Hi I'm trying to navigate to a shopping cart from inside a products page called merchandise and I can't seem to navigate using the header. I've tried using options and screenoptions but both aren't working and I'm thinking I'm putting the navigation in the wrong place? I've loaded the shopping cart nav into the merch nav but I can't seem to navigate to this from the shopping cart icon component
MerchNav
import React from 'react';
import { StyleSheet, Text, View, Image, SafeAreaView, Dimensions } from 'react-native';
import { useDimensions } from '#react-native-community/hooks';
import { createStackNavigator, HeaderStyleInterpolators } from '#react-navigation/stack';
import ArtistMerch from '../pages/ArtistPages/ArtistMerch';
import ShoppingCartNav from '../navigation/ShoppingCartNav'
import ShoppingCartIcon from '../components/ShoppingCartIcon';
const Stack = createStackNavigator();
export default function MerchNav() {
console.log(useDimensions());
return (
<Stack.Navigator>
<Stack.Screen name = {'ProductsList'} component={ArtistMerch} options={({navigation}) => ({headerStyle: {backgroundColor: 'lightblue'},
headerTitle: (
<View style={styles.logo}>
<Text style={styles.logo}> Merchandise </Text>
</View>),
headerTitleStyle: { alignSelf: 'center', top: 0},
headerRight: () => (
<ShoppingCartIcon onPress={() => navigation.navigate("ShoppingCart")}/>)})}/>
<Stack.Screen name = {'ShoppingCart'} component={ShoppingCartNav} options={{headerStyle: {backgroundColor: 'lightblue'},
headerTitle: (
<View style={styles.logo}>
<Text style={styles.logo}> Shopping Cart </Text>
</View>)}}/>
</Stack.Navigator>
);
}
ShoppingCartNav
import React from 'react';
import { StyleSheet, Text, View, Image, SafeAreaView, Dimensions } from 'react-native';
import { useDimensions } from '#react-native-community/hooks';
import { createStackNavigator, HeaderStyleInterpolators } from '#react-navigation/stack';
import ShoppingCart from '../pages/ArtistPages/ShoppingCart';
const Stack = createStackNavigator();
export default function ShoppingCartNav() {
console.log(useDimensions());
return (
<Stack.Navigator>
<Stack.Screen name = {'Cart'} component={ShoppingCart} options={{headerStyle: {backgroundColor: 'lightblue'},
headerTitle: (
<View style={styles.logo}>
<Text style={styles.logo}> Shopping Cart </Text>
</View>)}}/>
</Stack.Navigator>
);
}
You have to accept navigation as props inside your MerchNav component. MerchNav({navigation})
I have created an application using React native expo where I have two screens - Splash & Login. So, after the Splash screen appears for 3 seconds it goes to the Login Screen. Now, in the Login Screen I just want to perform a single task - by clicking the Sign in button I want to switch the login Screen back to the Splash Screen.
Below I have provided the code of my three classes-
App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import store from './src/store';
import {Provider} from 'react-redux';
import Splash from './src/Splash';
import Login from './src/Login';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state ={currentScreen:'Splash'};
console.log('Start doing some tasks for about 3 seconds')
setTimeout( ()=> {
console.log('Done some tasks for about 3 second')
this.setState({currentScreen: 'Login'})
} , 3000)
}
render() {
const {currentScreen} = this.state;
let mainScreen = currentScreen === 'Splash' ?
<Splash/> : <Login/>
return mainScreen
}
}
Login.js
import React, {Component} from 'react';
import { StyleSheet, Text, View, Image, TouchableWithoutFeedback,
StatusBar, TextInput, SafeAreaView, Keyboard, TouchableOpacity,
KeyboardAvoidingView } from 'react-native';
class Login extends Component {
render() {
return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="light-content"/>
<KeyboardAvoidingView
behavior = "padding"
style={styles.container}
>
<TouchableWithoutFeedback
style = {styles.container}
onPress = {Keyboard.dismiss}
>
<View style = {styles.logoContainer}>
<View style = {styles.logoContainer}>
<Text style={styles.title}>
Account Information
</Text>
</View>
<View style={styles.infoContainer}>
<TextInput
style = {styles.input}
placeholder = "Enter User name/Email"
placeholderTextColor = 'rgba(255,255,255,0.8)'
keyboardType = 'email-address'
returnKeyType = 'next'
autoCorrect= {false}
onSubmitEditing = {() => this.refs.txtPassword.focus()}
/>
<TextInput
style = {styles.input}
placeholder = "Enter Password"
placeholderTextColor = 'rgba(255,255,255,0.8)'
returnKeyType = 'go'
autoCorrect= {false}
ref = {"textPassword"}
/>
<TouchableOpacity style={styles.buttonContainer}>
<Text style={styles.buttonText}>SIGN IN</Text>
</TouchableOpacity>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
}
export default Login;
Splash.js
import React, {Component} from 'react';
import { StyleSheet, Text, View } from 'react-native';
class Splash extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.title}>Hello Splash</Text>
</View>
);
}
}
export default Splash;
Then I just installed the react navigation using the following command-
npm install --save react-navigation
And then followed the React native expo documantation-
https://docs.expo.io/versions/latest/react-native/navigation/
But none of them was working according to the plan. So, I just need one easy solution to go from the Login screen to Splash screen by the Sign In button press. It would be very nice if anyone help me about this.
You can make use of react-navigation for navigating from Splash screen to login and back.
I have made some changes to your code.
App.js
import React from "react";
import { createStackNavigator, createAppContainer } from "react-navigation";
import SplashScreen from "./Splash";
import Login from "./Login";
const AppNavigator = createStackNavigator({
SplashScreen: {
screen: SplashScreen
},
Login: {
screen: Login
}
});
export default createAppContainer(AppNavigator);
Splash.js
import React, { Component } from "react";
import { StyleSheet, Text, View } from "react-native";
class Splash extends Component {
constructor(props) {
super(props);
setTimeout(() => {
props.navigation.navigate("Login");
}, 3000);
}
render() {
return (
<View style={styles.container}>
<Text style={styles.title}>Hello Splash</Text>
</View>
);
}
}
export default Splash;
Login.js
import React, { Component } from "react";
import {
StyleSheet,
Text,
View,
Image,
TouchableWithoutFeedback,
StatusBar,
TextInput,
SafeAreaView,
Keyboard,
TouchableOpacity,
KeyboardAvoidingView
} from "react-native";
class Login extends Component {
render() {
const { navigation } = this.props;
return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="light-content" />
<KeyboardAvoidingView behavior="padding" style={styles.container}>
<TouchableWithoutFeedback
style={styles.container}
onPress={Keyboard.dismiss}
>
<View style={styles.logoContainer}>
<View style={styles.logoContainer}>
<Text style={styles.title}>Account Information</Text>
</View>
<View style={styles.infoContainer}>
<TextInput
style={styles.input}
placeholder="Enter User name/Email"
placeholderTextColor="rgba(255,255,255,0.8)"
keyboardType="email-address"
returnKeyType="next"
autoCorrect={false}
onSubmitEditing={() => this.refs.txtPassword.focus()}
/>
<TextInput
style={styles.input}
placeholder="Enter Password"
placeholderTextColor="rgba(255,255,255,0.8)"
returnKeyType="go"
autoCorrect={false}
ref={"textPassword"}
/>
<TouchableOpacity style={styles.buttonContainer} onPress={() => navigation.navigate("SplashScreen")}>
<Text style={styles.buttonText}>SIGN IN</Text>
</TouchableOpacity>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
}
export default Login;
Also I would suggest reading the docs of react-navigation. The examples given there are simple.
https://reactnavigation.org/docs/en/hello-react-navigation.html
Change the code of App.js. you have already install react navigation.
App.js :
import { StyleSheet, Text, View } from 'react-native';
import {createStackNavigator} from 'react-navigation';
import store from './src/store';
import {Provider} from 'react-redux';
import SplashScreen from './src/Splash';
import LoginScreen from './src/Login';
const App = createStackNavigator({
Splash: { screen: SplashScreen },
Login: { screen: LoginScreen },
});
export default App;
On Login screen sign button onPress :
this.props.navigation.goBack();
I am currently learning React Native and was having some issue with React-navigation.
What I am trying to do is switch screen when the "button" is being pressed.
In the "button", I have:
onPress={() =>
navigate('Home')}
I have const { navigate } = this.props.navigation; before the return statement.
When I run it, I am getting "Cannot read property 'navigate' of undefined.
I guess it is I have to place this.props.navigation somewhere.
Here are my two files:
"IntroPageFive" is the one that has the button and "react-navigation".
I would like to go to "IntroPageOne" when the button is being clicked.
Code for "IntroPageFive":
import React from 'react';
import { Text, View, Image, Linking, Button, TouchableOpacity } from 'react-native';
import PlaceholderImage from '../images/placeholder_thumbnail.png';
import SignInFooter from './signInFooter';
import { createStackNavigator } from 'react-navigation';
import IntroPageOne from './introPageOne';
const App = createStackNavigator({
Home: { screen: IntroPageOne },
});
class IntroPageFive extends React.Component {
render() {
const {
headerTextStyle,
thumbnailStyle,
viewStyle,
subTextStyle,
mainTextSection,
footerSectionStyle,
startButtonStyle,
startButtonTextStyle,
signInButtonStyle ,
signInButtonTextStyle
} = styles;
const { navigate } = this.props.navigation;
return (
<View style={viewStyle}>
<Image style={thumbnailStyle} source={require('../images/placeholder_thumbnail.png')} />
<View style={mainTextSection}>
<Text style={headerTextStyle}>Take A Ride For</Text>
<Text style={headerTextStyle}>Your Favorite Car!</Text>
</View>
<View>
<TouchableOpacity
onPress={() =>
navigate('Home')
}
style={startButtonStyle}
>
<Text style={startButtonTextStyle}>LET'S GET STARTED</Text>
</TouchableOpacity>
</View>
<View style={footerSectionStyle}>
<SignInFooter />
</View>
</View>
);
}
}
export default IntroPageFive;
Here is the code for "IntroPageOne":
import React from 'react';
import { Text, View, Image, Linking } from 'react-native';
import PlaceholderImage from '../images/placeholder_thumbnail.png';
import SignInFooter from './signInFooter';
const IntroPageOne = () => {
const { headerTextStyle, thumbnailStyle, viewStyle, subTextStyle } = styles;
return (
<View style={viewStyle} >
<Image style={thumbnailStyle} source={require('../images/placeholder_thumbnail.png')} />
<Text style={headerTextStyle}>Forget Everything You</Text>
<Text style={headerTextStyle}>Know About Making</Text>
<Text style={headerTextStyle}>Deals For Your Car</Text>
<Text style={subTextStyle}>Deal negotiation powered by AI</Text>
<SignInFooter />
</View>
);
};
};
export default IntroPageOne;
Could anyone please tell me how to fix this issue?
Thank you.