Search code examples
javascriptreact-nativeasynchronousgoogle-cloud-firestorereact-native-image-picker

How to await for the react native Image Picker callback function response?


I want to make a function that uploads a photo picked from the react-native-image-picker to firestore, and then returns the value of the URL of the uploaded image. The photo uploads succesfully and I can print in console the download URL, the problem is that when I try to return the URL in the function it is undefined. I tried using an async function to await for the image picker response to finish before I return its value, but it still returns {"_U": 0, "_V": 0, "_W": null, "_X": null}.

uploadImg: async () =>{
        await ImagePicker.launchImageLibrary({ mediaType: 'photo' }, response => {
            if (response.error) {
                alert('Something went wrong');
            } else {
                try {
                    const { path, uri } = response;
                    const fileSource = Platform.OS === 'android' ? uri : path;
                    const { fileName } = response;
                    const storageRef = storage().ref(fileName);
                    
                    storageRef.putFile(fileSource).on('state_changed', snapshot => {
                        switch (snapshot.state) {
                            case 'running':
                                setImageURI(null);
                                break;
                            case 'success':
                                snapshot.ref.getDownloadURL().then(downloadURL => {
                                    setImageURI(downloadURL);
                                    //This console log works, and actually prints the correct url
                                    console.log(`Download URL ${downloadURL}`); 
                                });
                                break;
                            default:
                                break;
                        }
                        
                    });
                } catch (error) {
                    console.log(error)
                }
            }
        }); 
        return imageURI;
    }

I'm pretty sure the problem is not with the state, uploading the picture, or the image picker response. It is likely a wrong usage of the asynchronous functions.


Solution

  • This is because you are returning from your function before the firebase call finishes executing. I made some updates to your code so the function can await a firebase response.

    uploadToFirebase: ( fileName, filesource )=>new Promise((resolve, reject)=>{
      const storageRef = storage().ref(fileName);
      storageRef.putFile(fileSource).on('state_changed', snapshot => {
        switch (snapshot.state) {
          case 'running':
            setImageURI(null);
            break;
          case 'success':
            snapshot.ref.getDownloadURL().then(downloadURL => {
              setImageURI(downloadURL);
              //This console log works, and actually prints the correct url
              console.log(`Download URL ${downloadURL}`); 
            });
            break;
          default:
            break;
        }
        resolve();
      });
    })
    
    uploadImg: async () =>{
      let response = await ImagePicker.launchImageLibraryAsync({ mediaType: 'photo' });
      if (response.error) {
        alert('Something went wrong');
      } else {
        const { path, uri } = response;
        const fileSource = Platform.OS === 'android' ? uri : path;
        const { fileName } = response;
        await uploadToFirebase(fileName, fileSource)
      }
      return imageURI;
    }