I was just trying to start learning React-Native and Expo-Go for the past few days. I was simply trying to access some camera, basically just want to start with a MainPage then navigate to the CameraPage that can scan an item, but got some Render Error:
ERROR [TypeError: Invalid attempt to destructure non-iterable instance.In order to be iterable, non-array objects must have a Symbol.iterator method.]
I am working on a window setup with an Expo-Go in my iphone. I think the problem might be from my expo-camera version. Really new to this so if there are any better approach to this, I'm free for any suggestion.
├── @expo/[email protected]
├── @react-navigation/[email protected]
├── @react-navigation/[email protected]
├── @react-navigation/[email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]
MainPage
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import React, { useState, useEffect } from 'react';
import { View, Text, Button } from 'react-native';
import { Camera } from 'expo-camera';
import HomeScreen from './HomeScreen';
import DetailsScreen from './DetailsScreen';
import SettingsScreen from './SettingsScreen';
import CameraScreen from './CameraScreen';
export type RootStackParamList = {
Home: undefined;
Details: undefined;
Settings: undefined;
Camera: undefined;
};
const Stack = createNativeStackNavigator<RootStackParamList>();
export default function PermissionsScreen({ onGranted }: { onGranted?: () => void }) {
const [status, setStatus] = useState<'undetermined' | 'granted' | 'denied' | null>(null);
useEffect(() => {
Camera.getCameraPermissionsAsync().then(res => {
setStatus(res.granted ? 'granted' : 'denied');
if (res.granted && onGranted) onGranted();
});
}, []);
const ask = async () => {
const res = await Camera.requestCameraPermissionsAsync();
setStatus(res.granted ? 'granted' : 'denied');
if (res.granted && onGranted) onGranted(); // ✅ only call if defined
};
if (status === 'undetermined' || status === null) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Checking camera permissions …</Text>
</View>
);
}
if (status === 'denied') {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Need camera permission</Text>
<Button title="Grant Permission" onPress={ask} />
</View>
);
}
return (
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
name="Home"
component={HomeScreen}
options={({ navigation }) => ({
title: 'Home',
headerRight: () => (
<View style={{ flexDirection: 'row' }}>
<Button
title="Settings"
onPress={() => navigation.navigate('Settings')}
/>
<Button
title="Camera"
onPress={() => navigation.navigate('Camera')}
/>
</View>
),
})}
/>
<Stack.Screen name="Details" component={DetailsScreen} />
<Stack.Screen name="Settings" component={SettingsScreen} />
<Stack.Screen name="Camera" component={CameraScreen} />
</Stack.Navigator>
)
CameraPage
const toggleCameraFacing = () => {
setFacing(current => (current === 'back' ? 'front' : 'back'));
};
return (
<View style={styles.container}>
<Camera style={styles.camera} type={facing} />
<View style={styles.buttonContainer}>
<TouchableOpacity style={styles.button} onPress={toggleCameraFacing}>
<Text style={styles.text}>Flip Camera</Text>
</TouchableOpacity>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center' },
message: { textAlign: 'center', paddingBottom: 10 },
camera: { flex: 1 },
buttonContainer: {
position: 'absolute',
bottom: 64,
flexDirection: 'row',
backgroundColor: 'transparent',
width: '100%',
paddingHorizontal: 64,
},
button: { flex: 1, alignItems: 'center' },
text: { fontSize: 24, fontWeight: 'bold', color: 'white' },
});