0

i am trying to make a photo uploader to firebase in react native. I followed a tutorial and adopted the code 1-on-1. However, after I want to execute the code everything appears to work until the code has to be uploaded then I get the following error:

Possible Unhandled Promise Rejection (id: 0): Error: An unknown error has occurred. fn@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2132:45 http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:127402:44 putFile@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:137147:104 uploadImage@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:210966:91 touchableHandlePress@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:54240:47 touchableHandlePress@[native code] _performSideEffectsForTransition@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:52872:36 _performSideEffectsForTransition@[native code] _receiveSignal@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:52798:46 _receiveSignal@[native code] touchableHandleResponderRelease@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:52677:26 touchableHandleResponderRelease@[native code] invokeGuardedCallbackImpl@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:8997:21 invokeGuardedCallback@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9093:42 invokeGuardedCallbackAndCatchFirstError@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9097:36 executeDispatch@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9204:48 executeDispatchesInOrder@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9224:26 executeDispatchesAndRelease@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9329:35 forEach@[native code] forEachAccumulated@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9319:22 runEventsInBatch@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9353:27 runExtractedPluginEventsInBatch@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:9441:25 http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:10467:42 batchedUpdates$1@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:21921:20 batchedUpdates@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:10415:36 _receiveRootNodeIDEvent@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:10466:23 receiveTouches@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:10496:34 __callFunction@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2650:49 http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2363:31 __guard@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2604:15 callFunctionReturnFlushedQueue@http://localhost:8081/index.bundle?platform=android&dev=true&minify=false:2362:21 callFunctionReturnFlushedQueue@[native code]

Is anyone familiar with uploading images to firebase? in the tutorial they use uuid but for some reason the app breaks when I try to use this, so I left it out. this is the corresponding code:

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, Image, Button, ScrollView, ImageBackground, Dimensions,TouchableOpacity,  FlatList,
  AsyncStorage} from 'react-native';
import { Avatar, ListItem } from 'react-native-elements';
import Icon from 'react-native-vector-icons/FontAwesome';
import ImagePicker from 'react-native-image-picker';
import firebase from 'react-native-firebase';






const SCREEN_WIDTH = Dimensions.get("window").width;
const list = [
  {
    title: '',
    icon: 'cake',
    url: 'ProfileSettings',
  },


]

const options = {
  title: 'Select Image',
  storageOptions: {
    skipBackup: true,
    path: 'images'
  }
};

const ImageRow = ({ image, windowWidth, popImage }) => (
  <View>
    <Image
      source={{ uri: image }}
      style={[styles.img, { width: windowWidth / 2 - 15 }]}
      onError={popImage}
    />
  </View>
);




class profileScreen extends Component {

  constructor(props){
    super(props);
    this.state = {
      first: '',
      place: '',
      province: '',
      uid: '',
      profileImg: '',
      email: '',
      imgSource: '',
      uploading: false,
      progress: 0,
      images: []

    }
}



getUserData = (user) => {
  console.log(user);
  let ref = firebase.database().ref('Users/' + user);
  ref.on('value' , snapshot =>{
      var state = snapshot.val();
      this.setState({
        first: state.firstname,
        place: state.place,
        province: state.province,
        uid: user,
        profileImg: state.profileImg,
        birthday: state.birthday,
        email: state.email,
        year: state.registered.split("-",1)
      })
    })

}


  componentDidMount(){
    let user = firebase.auth().currentUser;
    console.log(user);
    console.log('test');
    this.getUserData(user.uid); 
    let images;
    AsyncStorage.getItem('images')
      .then(data => {
        images = JSON.parse(data) || [];
        this.setState({
          images: images
        });
      })
      .catch(error => {
        console.log(error);
      });
  }

   /**
   * Select image method
   */
  pickImage = () => {
    ImagePicker.showImagePicker(options, response => {
      if (response.didCancel) {
        console.log('You cancelled image picker ');
      } else if (response.error) {
        alert('And error occured: ', response.error);
      } else {
        const source = { uri: response.uri };
        this.setState({
          imgSource: source,
          imageUri: response.uri
        });
        console.log(source);
      }
    });
  };
  /**
   * Upload image method
   */
  uploadImage = () => {
    const ext = this.state.imageUri.split('.').pop();      // Extract image extension
const filename = `unique image' + ${ext}`;             // Generate unique name
const imageRef = firebase.storage().ref('tutorials/images').child(filename +ext);
let mime = 'image/jpg';
imageRef.put(this.state.imageUri, { contentType: mime }).then((snapshot)=>{
    console.log('Image uploaded successfully.')
}).catch((error)=>{
    console.log('Image uploading failed:' + error);
});

  };
  /**
   * Remove image from the state and persistance storage
   */
  removeImage = imageIndex => {
    let images = this.state.images;
    images.pop(imageIndex);
    this.setState({ images });
    AsyncStorage.setItem('images', JSON.stringify(images));
  };



  render() {
    const { uploading, imgSource, progress, images } = this.state;
    const windowWidth = Dimensions.get('window').width;
    const disabledStyle = uploading ? styles.disabledBtn : {};
    const actionBtnStyles = [styles.btn, disabledStyle];
    return (
      <ScrollView  style={styles.scorllVert}>
      <View style={{ alignItems: 'flex-start', justifyContent: 'center', marginBottom: 40 }}>
          <View style={styles.intro}>

          <Text style={styles.introText}>Hoi, ik ben {this.state.first}{"\n"}<Text style={styles.introTextSpan}>Lid geworden in {this.state.year}</Text></Text>

            { this.state.profileImg ?
                <Avatar size="large" rounded source={{uri: this.state.profileImg,}} onPress={() => console.log("Works!")} activeOpacity={0.7} />
                :
                <Avatar size="large" rounded title="GLR" onPress={() => console.log("Works!")} activeOpacity={0.7} />
            }



          </View>
          <View style={styles.divider}>

          </View>
          <View style={styles.about}>
           <Text style={styles.profileName}>Over</Text>
            <View style={styles.aboutLiving}>
              <Icon name='home'  style={styles.icon}/>
              <Text style={styles.aboutText}>Woont in {this.state.place}, {this.state.province}</Text>
            </View>
          </View>

          <View style={styles.divider}>

          </View>
          <View style={styles.about}>
           <Text style={styles.profileName}>Door {this.state.first}  versterkt</Text>
            <View style={styles.aboutLiving}>
              <Icon name='check-circle'  style={[styles.icon, styles.iconGreen]}/>
              <Text style={styles.aboutText}>E-mail adres</Text>
            </View>
          </View>

          <View style={styles.divider}>

          </View>

          <View style={styles.about}>
           <Text style={styles.profileName}>Recente activiteiten</Text>
          <Text >N.v.t.</Text>

          <TouchableOpacity
              style={actionBtnStyles}
              onPress={this.pickImage}
              disabled={uploading}
            >
              <View>
                <Text style={styles.btnTxt}>Pick image</Text>
              </View>
            </TouchableOpacity>

            {imgSource !== '' && (
              <View>
                <Image source={imgSource} style={styles.image} />
                {uploading && (
                  <View
                    style={[styles.progressBar, { width: `${progress}%` }]}
                  />
                )}
                <TouchableOpacity
                  style={actionBtnStyles}
                  onPress={this.uploadImage}
                  disabled={uploading}
                >
                  <View>
                    {uploading ? (
                      <Text style={styles.btnTxt}>Uploading ...</Text>
                    ) : (
                      <Text style={styles.btnTxt}>Upload image</Text>
                    )}
                  </View>
                </TouchableOpacity>
              </View>
            )}

            <View>
              <Text
                style={{
                  fontWeight: '600',
                  paddingTop: 20,
                  alignSelf: 'center'
                }}
              >
                {images.length > 0
                  ? 'Your uploaded images'
                  : 'There is no image you uploaded'}
              </Text>
            </View>
            <FlatList
              numColumns={2}
              style={{ marginTop: 20 }}
              data={images}
              renderItem={({ item: image, index }) => (
                <ImageRow
                  windowWidth={windowWidth}
                  image={image}
                  popImage={() => this.removeImage(index)}
                />
              )}
              keyExtractor={index => index}
            />


          </View>





      </View>
      </ScrollView>

    );
  }


  }

  const styles = StyleSheet.create({
    profileName:{
      fontWeight: 'bold',
      fontSize: 22,
      marginTop: 20,
    },
    list:{
      marginTop: 40,
      width: '100%'
    },intro:{
      flex: 1,
      flexDirection: 'row',
      flexWrap: 'wrap',
      alignItems: 'flex-start',
      padding: 25,
      marginBottom: 30,
      paddingTop: 80,
    },
    introText:{
      marginLeft: 0,
      marginRight: 50,
      fontSize: 22,
      fontWeight: "700",
      marginTop:15,
    },
    introTextSpan:{
      marginLeft: 0,
      marginRight: 40,
      fontSize: 15,
      fontWeight: "200",
      marginTop:50,
    },
    divider:{
      width: SCREEN_WIDTH-50,
      padding: 10,
      borderBottomColor: 'grey',
      borderBottomWidth: 0.5,
      marginTop: 10,
      marginLeft: 25
    },
    about:{
      paddingLeft: 25,
    },
    aboutLiving:{
      flexDirection: 'row',
      flexWrap: 'wrap',
      alignItems: 'flex-start',
      paddingTop: 10
    },
    icon:{
      fontSize: 18
    },
    aboutText:{
      marginLeft: 30
    },
    iconGreen:{
      color: 'green'
    }
    ,
    button: {
        marginTop: 30,
        marginBottom: 20,
        paddingVertical: 10,
        alignItems: 'center',
        backgroundColor: '#019BB4',
        width: 300
    },
    buttonText: {
        fontSize: 20,
        fontWeight: 'bold',
        color: '#fff'
    },
    scorllVert:{
      marginBottom: 40
    },
    btn: {
      paddingLeft: 20,
      paddingRight: 20,
      paddingTop: 10,
      paddingBottom: 10,
      borderRadius: 20,
      backgroundColor: 'rgb(3, 154, 229)',
      marginTop: 20,
      alignItems: 'center'
    },
    disabledBtn: {
      backgroundColor: 'rgba(3,155,229,0.5)'
    },
    btnTxt: {
      color: '#fff'
    },
    image: {
      marginTop: 20,
      minWidth: 200,
      height: 200,
      resizeMode: 'contain',
      backgroundColor: '#ccc',
    },
    img: {
      flex: 1,
      height: 100,
      margin: 5,
      resizeMode: 'contain',
      borderWidth: 1,
      borderColor: '#eee',
      backgroundColor: '#ccc'
    },
    progressBar: {
      backgroundColor: 'rgb(3, 154, 229)',
      height: 3,
      shadowColor: '#000',
    }
  })



  export default profileScreen;

I am fairly new to react native and would like to upload images, is there anyone who can help me get this done? Even if there are other methods, I am open to that!

Joppe Meijers
  • 301
  • 4
  • 24

2 Answers2

0

Try wrapping your uploadImage function in a try..catch and see if you can get a clearer error message in catch

0

Try this code for uploading the image,

const ext = this.state.imageUri.split('.').pop();      // Extract image extension
const filename = `unique image' + ${ext}`;             // Generate unique name
const imageRef = firebase.storage().ref('tutorials/images).child(filename +ext);
let mime = 'image/jpg';
imageRef.put(this.state.imageUri, { contentType: mime }).then((snapshot)=>{
    console.log('Image uploaded successfully.')
}).catch((error)=>{
    console.log('Image uploading failed');
});
Anurodh Singh
  • 814
  • 5
  • 9
  • Thanks for you help, but only 1 question, where does imageUrl come from after imageRef.put( ? – Joppe Meijers Mar 09 '20 at 22:06
  • It is the same state variable(imageUri). I am updating the code. – Anurodh Singh Mar 10 '20 at 04:08
  • i updated the code above with your function but sadly it doesn't upload the image and ends at 'Image uploading failed: Error: an unkown error has occurred – Joppe Meijers Mar 10 '20 at 07:51
  • Then please check your rules in the `Storage` section under `Rules` tab(second tab) on the firebase console. Default rules don't let you write anything if you are not authenticated. If you don't want any authentication to write access then you can simply modify that line to `allow read, write;` – Anurodh Singh Mar 10 '20 at 09:15
  • the rules are all on allow : `rules_version = '2'; 2 service firebase.storage { 3 match /b/{bucket}/o { 4 match /{allPaths=**} { 5 allow read, write; 6 } 7 } 8 }` – Joppe Meijers Mar 10 '20 at 14:44