Home > OS >  Difficulties handling asynchronous taks using image-picker and copying files in react-native
Difficulties handling asynchronous taks using image-picker and copying files in react-native

Time:05-05

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

  • Related