5

I am using Expo Camera to take some user pictures for a profile form. What is happening is when I try to set camera's ref to a state it crashes and throw the following error.

Couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'? See https://reactnavigation.org/docs/getting-started for setup instructions.

Everything is inside a Navigation Container and I really can't figure out what is happening.

Every time I comment ref={(ref) => console.tron.log(ref)} from Expo Camera component everything works fine, but when I uncomment the ref line I get the error.

I am stuck here since last week and nothing on internet about this problem...

Thanks in advance =)

Error saying I am maybe not using inside a Navigation Container

App.js

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { AuthProvider } from './src/context/authContext';

import Routes from './src/routes';
import Theme from './src/theme';
import './src/config/reactotron.config';

export default function App() {
    return (
        <Theme>
            <AuthProvider>
                <NavigationContainer>
                    <Routes />
                </NavigationContainer>
            </AuthProvider>
        </Theme>
    );
}

routes.js

import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';

import arrowLeft from '../../assets/img/arrow-left-header.png';

import SignUp from '../pages/auth/SignUp';
import Profile from '../pages/auth/Profile';
import Login from '../pages/auth/Login';
import Habits from '../pages/auth/Habits';
import AddChildren from '../pages/auth/AddChildren';
import ChildProfile from '../pages/auth/ChildProfile';
import RegisterFinish from '../pages/auth/RegisterFinish';
import { CameraView } from '../components';

const AuthStack = createStackNavigator();
const theme = {
    color: {
        brandPrimary: '#16B4A1',
        white: '#fff',
    },
};

const AuthRoutes = () => {
    return (
        <AuthStack.Navigator
            screenOptions={{
                headerTintColor: theme.color.white,
                headerStyle: {
                    backgroundColor: theme.color.brandPrimary,
                },
                cardStyle: {
                    backgroundColor: theme.color.white,
                },
                headerBackTitle: 'Voltar',
            }}
        >
            <AuthStack.Screen
                name='Profile'
                component={Profile}
                options={{
                    headerLeft: null,
                }}
            />
            <AuthStack.Screen
                name='Login'
                component={Login}
                options={{ headerShown: false }}
            />

            <AuthStack.Screen
                name='SignUp'
                component={SignUp}
                options={{ headerShown: false }}
            />
            
            <AuthStack.Screen
                name='RegisterFinish'
                component={RegisterFinish}
                options={{
                    headerLeft: null,
                    headerShown: false,
                }}
            />
            <AuthStack.Screen
                name='TakeAPicture'
                component={CameraView}
                options={{
                    headerLeft: null,
                    headerShown: false,
                }}
            />
            <AuthStack.Screen name='Habits' component={Habits} />
            <AuthStack.Screen name='AddChildren' component={AddChildren} />
            <AuthStack.Screen name='ChildProfile' component={ChildProfile} />
        </AuthStack.Navigator>
    );
};

export default AuthRoutes;

CameraView.js

import React, { useState, useEffect, useRef } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import PropTypes from 'prop-types';
import { Camera } from 'expo-camera';
import { FontAwesome5 } from '@expo/vector-icons';

import { CameraButton, CameraButtonRing } from './styles';

const CameraView = ({ route, navigation }) => {
    const cameraRef = useRef()
    // CAMERA SETTINGS
    const [hasPermission, setHasPermission] = useState(null);
    const [type, setType] = useState(Camera.Constants.Type.front);

    useEffect(() => {
        console.tron.log('rolou')
        async function handleCameraPermission() {
            const { status } = await Camera.requestPermissionsAsync();
            setHasPermission(status === 'granted');
        }
        handleCameraPermission();
    }, []);

    const handleTakePictureButton = async () => {
        if (!cameraRef) {
            console.tron.log('Não tem cam ref')
            return
        };
        let photo = await cameraRef.takePictureAsync();
        console.tron.log(photo)
        handlePicture(photo)
    }

    return (
        <View style={{ flex: 1 }}>
            <Camera
                style={{ flex: 1 }}
                type={type}
                ref={(ref) => console.tron.log(ref)}
            >
                <View
                    style={{
                        flex: 1,
                        backgroundColor: 'transparent',
                        flexDirection: 'row',
                        border: '1px solid red '
                    }}
                >
                    <TouchableOpacity
                        style={{
                            // flex: ,
                            // alignSelf: 'flex-end',
                            // alignItems: 'center',
                            position: 'absolute',
                            bottom: 40,
                            right: 32,
                        }}
                        onPress={() => {
                            setType(
                                type === Camera.Constants.Type.back
                                    ? Camera.Constants.Type.front
                                    : Camera.Constants.Type.back
                            );
                        }}
                    >
                        <FontAwesome5 name='sync-alt' size={32} color='#fff' />
                    </TouchableOpacity>

                    <TouchableOpacity
                        style={{
                            // flex: 0.1,
                            alignSelf: 'flex-end',
                            height: 56,
                            width: 56,
                            backgroundColor: 'transparent',
                            marginLeft: 'auto',
                            marginRight: 'auto',
                            marginBottom: 24,
                            border: '1px solid red'
                        }}
                        onPress={handleTakePictureButton}
                    >
                        <View style={{position: 'relative'}}>
                            <CameraButton />
                            <CameraButtonRing />
                        </View>
                    </TouchableOpacity>
                </View>
            </Camera>
        </View>
    );
};


export default CameraView;
Hagai Harari
  • 2,767
  • 3
  • 11
  • 23
  • same issue with `expo-av` `Video` component – Hagai Harari Feb 28 '21 at 12:57
  • This seems to be related to this issue with using react native viewpager and react navigation together: https://github.com/callstack/react-native-viewpager/issues/226. Maybe you could adapt something from these examples referenced in the answer to that: https://github.com/callstack/react-native-viewpager/tree/master/example/src – Charlotte_Anne Mar 03 '21 at 19:05

1 Answers1

1

For anyone stumbling on this, I really don't know the reason behind, but what was crashing my app with the exact same error, was trying to log to Reactotron. It was the only thing in common with the code on the question, and after removing that, the application stopped crashing and worked just fine.

Now... if anyone discovers the reason, I would really like to know as well.

  • This is more appropriate as a comment than answer. – Debargha Roy Dec 24 '22 at 13:19
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/33469093) – MichaelMao Dec 26 '22 at 06:35