I’m trying to navigate to my page “CameraPage.js” but I’m getting this error “undefined is not an object (evaluating ‘navigation.navigate’)”. Can anybody see the problem? This ismy first question here so please tell me if I can be more specific.
Here’s my App.js:
import { StyleSheet, Text, View, TouchableOpacity, Pressable } from 'react-native'; import React, {useEffect, useState} from "react"; import { FontAwesome } from '@expo/vector-icons'; import { useNavigation } from '@react-navigation/native'; export default function App({ navigation }) { return ( <View style={styles.container}> <View style={styles.buttonContainer}> <TouchableOpacity onPress ={() => navigation.navigate('CameraFunction')}> <FontAwesome name="camera" size={100} color="#FFB6C1" /> </TouchableOpacity> <Pressable> <FontAwesome name="photo" size={100} color="#FFB6C1" /> </Pressable> </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#FFDBE9' }, buttonContainer: { backgroundColor: 'transparent', justifyContent: 'space-between', }, });
import {StyleSheet, Text, View, TouchableOpacity} from 'react-native'; import {Camera, CameraType} from 'expo-camera'; import {useEffect, useState} from "react"; export default function CameraPage() { const [hasPermission, setHasPermission] = useState(null); const [type, setType] = useState(CameraType.back); useEffect(() => { (async () => { const {status} = await Camera.requestCameraPermissionsAsync(); setHasPermission(status === 'granted'); })(); }, []); if (hasPermission === null) { return <View/>; } if (hasPermission === false) { return <Text>No access to camera</Text>; } return ( <View style={styles.container}> <Camera style={styles.camera} type={type}> <View style={styles.buttonContainer}> <TouchableOpacity style={styles.button} onPress={() => { setType(type === CameraType.back ? CameraType.front : CameraType.back); }}> <Text style={styles.text}> Flip </Text> </TouchableOpacity> </View> </Camera> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, }, camera: { flex: 1, }, buttonContainer: { flex: 1, backgroundColor: 'transparent', flexDirection: 'row', margin: 20, }, button: { flex: 0.1, alignSelf: 'flex-end', alignItems: 'center', }, text: { fontSize: 18, color: 'white', }, });
import React from 'react'; import {createStackNavigator} from '@react-navigation/stack'; import {NavigationContainer} from '@react-navigation/native'; import CameraPage from "../Camera/CameraPage"; const Routes = createStackNavigator(); export default function Navigator() { return ( <NavigationContainer> <Routes.Navigator> <Routes.Screen name="CameraFunction" component={CameraPage} /> </Routes.Navigator> </NavigationContainer> ); }
Advertisement
Answer
Your navigation container must be wrapped around the root of your application or otherwise the navigation object will not be passed to the components that you have defined as screens.
The following fixes your issue.
export default const App = () => { return ( <NavigationContainer> <Routes.Navigator> <Routes.Screen name="Home" component={HomeScreen} /> <Routes.Screen name="CameraFunction" component={CameraPage} /> </Routes.Navigator> </NavigationContainer> ); }
Your HomeScreen
contains the old code from App
, but now you can access the navigation object since we have defined HomeScreen as a screen inside the navigator. It will be passed to that screen by the navigation framework. Notice as well that HomeScreen
is the initial screen of your application.
export default function HomeScreen({ navigation }) { return ( <View style={styles.container}> <View style={styles.buttonContainer}> <TouchableOpacity onPress ={() => navigation.navigate('CameraFunction')}> <FontAwesome name="camera" size={100} color="#FFB6C1" /> </TouchableOpacity> <Pressable> <FontAwesome name="photo" size={100} color="#FFB6C1" /> </Pressable> </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#FFDBE9' }, buttonContainer: { backgroundColor: 'transparent', justifyContent: 'space-between', }, });
Notice, that you need to navigate back to the HomeScreen once you have navigated to the CameraPage. You can use the navigation object in the CameraPage as well and trigger navigation.goBack
to achieve this effect.