1

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
  }
});
5
  • Why are you saving whole picker response in the state If you only want the uri of the img?
    – Inder
    Commented May 4, 2022 at 13:50
  • @Inder thanks for pointing that, I will remove it. Still that is not the issue
    – sarli
    Commented May 4, 2022 at 13:57
  • What does decodeURIComponent() function do?
    – Inder
    Commented May 4, 2022 at 14:03
  • @Inder decodeURIComponent() function decodes a Uniform Resource Identifier (URI) component. It formats the uri so I can use the copy function
    – sarli
    Commented May 4, 2022 at 14:13
  • I think you're not even going to need that one. Add the code for that one too in the question.
    – Inder
    Commented May 4, 2022 at 14:28

1 Answer 1

2

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

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.