I'm adding a camera to an already developed react native project. I want to return the imageUri (set by takePicture in the camera component) to the calling component after the image is confirmed by user input to the image component.
Calling component:
<FAB style={styles.fab} test id="goToCamera" small icon="camera" onPress={() => navigation.navigate("Camera")}></FAB>
Camera component:
import React, { useState, useEffect, useRef, Component } from 'react';
import { StyleSheet, Text, View, TouchableOpacity, Button, Image } from 'react-native';
import { Camera, CameraType } from 'expo-camera';
import { setImageUri, imageUri } from "../screens/ImageValidationScreen";
import colors from "../config/colors";
function CameraScreen({ navigation }) {
const [hasPermission, setHasPermission] = useState(null);
const [type, setType] = useState(CameraType.back);
const [camera, setCamera] = useState(null);
const [imageUri, setImageUri] = useState(null);
const [cameraToggle, setCameraToggle] = useState(null);
useEffect(() => {
(async () => {
const { status } = await Camera.requestCameraPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
const takePicture = async () => {
if (camera) {
const data = await camera.takePictureAsync(null);
console.log(data.uri);
setImageUri(data.uri);
}
};
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} ref={(ref)=> setCamera(ref)}>
<View style={styles.buttonContainer}>`enter code here`
<TouchableOpacity
style={styles.captureButton}
onPress={() => {
takePicture();
navigation.navigate("Image");
}}>
</TouchableOpacity>
<TouchableOpacity
onPress={() => { setType(type === CameraType.back ? CameraType.front : CameraType.back); }}>
<Text style={styles.text}> Flip </Text>
</TouchableOpacity>
</View>
</Camera>
</View>
);
}
Image component:
import React, { useState, useEffect, useRef, Component } from 'react';
import { StyleSheet, Text, View, TouchableOpacity, Button, Image } from 'react-native';
import { Camera, CameraType } from 'expo-camera';
import imageUri from "../screens/CameraScreen"
import colors from "../config/colors";
function ImageValidationScreen({ navigation }) {
return (
<View>
<TouchableOpacity
onPress={() => {
navigation.navigate("CSS");
}}>
<Text style={styles.text}> Done </Text>
</TouchableOpacity>
{imageUri && <Image source={{ uri: imageUri }} />}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
text: {
fontSize: 20,
color: 'black',
},
});
export default ImageValidationScreen;
Right now, I think the imageUri is correctly retrieved/printed to the console, but is being incorrectly retrieved by the Image component. I'm not sure how to pass this value to the calling component. Thank you so much in advance!!
The best way to do this is by passing parameters to image routes, you can see the documentation here.
So, you can pass object in navigation.navigate
second parameter like this:
navigation.navigate("Image", {
imageUri: imageUri
});
In your case, you must get image URL from takePicture
promise and then pass it to navigate
method
const takePicture = async () => {
if (camera) {
const data = await camera.takePictureAsync(null);
console.log(data.uri);
setImageUri(data.uri);
return data.uri
}
};
and then the onPress
event
onPress={() => {
(async()=>{
const imageURI = await takePicture();
navigation.navigate("Image", {imageUri: imageURI});
})()
}}
To access imageURI
in image component, you can do this:
function ImageValidationScreen({ route, navigation }) {
const { imageUri } = route.params
return (
<View>
<TouchableOpacity
onPress={() => {
navigation.navigate("CSS");
}}>
<Text style={styles.text}> Done </Text>
</TouchableOpacity>
{imageUri && <Image source={{ uri: imageUri }} />}
</View>
);
}
Also, just remove import imageUri from "../screens/CameraScreen"
since imageUri isn't exported from CameraScreen file.
Haven't tested this though, let me know if it doesn't work.