Home > Mobile >  undefined is not an object (evaluating 'navigation.navigate') when trying to navigate to a
undefined is not an object (evaluating 'navigation.navigate') when trying to navigate to a

Time:05-26

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',
    },
});
Here is my CameraPage.js file:

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',
    },
});
Here is my navigation file:

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>
    );
}

CodePudding user response:

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.

CodePudding user response:

Add const navigation = useNavigation() in your App() like so:

export default function App({ navigation }) {

    const navigation = useNavigation() 

    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>
    );
}
  • Related