The following component CapturePhoto is used to take a photo using react-native Image Picker, once a photo is taken, I copy the photo file to a specific path that I pass as prop to this component from its parent ( a gallery of images that is a list of the CapturePhoto component) The reason I am copying the photo is that I cannot find another way to specify the path to Image picker as option.
The code works for taking a photo and copying the file image to the specific path but the photo is not being displayed until I take a second photo (delay)
I am learning react-native and Javascript at the same time, I know it's not the good way but I don't have time to learn Javascript first!
Any guidance provided would be much appreciated!
import React, { useState } from 'react';
import { TouchableOpacity, View, Image, StyleSheet, Text } from 'react-native';
import * as ImagePicker from 'react-native-image-picker';
import placeHolder from "./placeHolder.png"
export default function CapturePhoto({ photoPath }) {
let uri;
let decodedURI;
const [pickerResponse, setPickerResponse] = useState(null);
var RNFS = require('react-native-fs');
const copyPhoto = (source, destination) => {
if (source === undefined || destination === undefined) {
return;
} else {
RNFS.copyFile(source, destination)
.then((result) => {
console.log("\n\n>>>>>>>>>>>>The photo has been copied ")
}).catch((error) => {
console.log("\n\n>>>>>>>>>>>>Copy photo failed: ", error)
})
}
}
const onCameraPress = async () => {
const options = {
saveToPhotos: true,
mediaType: 'photo',
includeBase64: false,
};
ImagePicker.launchCamera(options, setPickerResponse);
uri = pickerResponse?.assets && pickerResponse.assets[0].uri;
console.log("\n\n>>>>>>>>>>>>destination photo: ", photoPath);
decodedURI = decodeURIComponent(uri)
await uri ? copyPhoto(decodedURI, photoPath) : console.log("\n\n>>>>>>>>>>>>The photo has not been copied ")
}
return (
<View style={{
justifyContent: 'center',
alignItems: 'center',
marginTop: 10
}}>
<TouchableOpacity onPress={() => onCameraPress()}>
<Image
style={styles.avatarImage}
source={uri ? { uri } : placeHolder}
/>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
avatarImage: {
height: 260,
width: 260,
overflow: 'hidden',
margin: 10
}
});
CodePudding user response:
You don't actually need any states for saving image picker response. If you want to save the uri of the image which was clicked you can have a state for it and add the code for it inside copyPhoto()
after file has been copied.
var RNFS = require('react-native-fs');
This statement should not be inside function. Everytime the component re-renders it will require it again. Add it like you've added import statements.
You should change your functions like this.
const copyPhoto = (source, destination) => {
if (source === undefined || destination === undefined) {
return;
} else {
RNFS.copyFile(source, destination)
.then((result) => {
console.log("\n\n>>>>>>>>>>>>The photo has been copied ");
})
.catch((error) => {
console.log("\n\n>>>>>>>>>>>>Copy photo failed: ", error);
});
}
};
const onCameraPress = async () => {
const options = {
saveToPhotos: true,
mediaType: "photo",
includeBase64: false
};
const result = await ImagePicker.launchCamera(options);
//if the user cancelled the process
if (result.didCancel) {
return alert("You cancelled the process");
}
const {assets} = result;
if (assets.length > 0) {
const decodedUri = decodeURIComponent(assets[0].uri);
copyPhoto(decodedUri, photoPath);
}
};