title: uri should not be an empty string in React Native
body: <p>I am trying to render either an image profile from firebase storage or a default avatar which is in my project img folder, depending on whether or not the current user has a profile or not. While the following code displays either the user image or the avatar image perfectly fine in my Menu.js :</p>
  
  <pre><code>import React, { Component } from 'react';
  import { View, Text, Image } from 'react-native';
  import { Actions } from 'react-native-router-flux';
  import { Content, List, ListItem, Thumbnail } from 'native-base';
  import firebase from 'firebase';
  import Helpers from '../../lib/helpers';
  
  class Menu extends Component {
  constructor(props) {
      super(props);
      this.state = { 
          avatarUrl: '',
          userName: '',
          userLastname: '',
          userEmail: '',
          userBio: '',
          uid: ''
      };
  }
  
  
  async componentWillMount() {
      try {
        const user = await firebase.auth().currentUser;
  
        Helpers.getImageUrl(user.uid, (imageUrl) =&gt; {
          this.setState({ avatarUrl: imageUrl });
        });
        Helpers.getUserName(user.uid, (name) =&gt; {
          this.setState({ userName: name });
        });
        Helpers.getUserLastname(user.uid, (lastname) =&gt; {
          this.setState({ userLastname: lastname });
        });
        Helpers.getUserEmail(user.uid, (email) =&gt; {
          this.setState({ userEmail: email });
        });
        Helpers.getUserBio(user.uid, (bio) =&gt; {
          this.setState({ userBio: bio });
        });
  
        this.setState({ uid: user.uid });
      } catch (error) {
          console.log(error);
      }
  }  
  
  mostrarAvatar() {
      if (this.state.avatarUrl) {
          return (&lt;Image 
          style={{ width: 100, height: 100, borderRadius: 150 / 2 }}
          source={{ uri: this.state.avatarUrl }}
          /&gt;);
      } 
      return (&lt;Thumbnail 
              source={require('../../img/avatar.png')}
              large
      /&gt;); 
  }
  
  mostrarNombreUsuario() {
      if (this.state.userName !== '') {
          return &lt;Text style={{ color: 'white', fontSize: 15 }}&gt;{this.state.userName}&lt;/Text&gt;;
      }
      return &lt;Text style={{ color: 'white', fontSize: 15 }}&gt;Usuario&lt;/Text&gt;; 
  }
  
  render() {
      const { userName, userLastname, userEmail, userBio, avatarUrl } = this.state;
      return (
          &lt;View style={{ flex: 1 }}&gt;
              &lt;View style={{ flex: 1, backgroundColor: '#2c3e50', justifyContent: 'center', alignItems: 'center' }}&gt;
                  {this.mostrarAvatar()}
                  {this.mostrarNombreUsuario()}
              &lt;/View&gt;
              &lt;View style={{ flex: 2 }}&gt;
                  &lt;Content&gt;
                      &lt;List&gt;
                          &lt;ListItem onPress={() =&gt; Actions.albumList()}&gt;
                              &lt;Text&gt;Los más escuchados&lt;/Text&gt;
                          &lt;/ListItem&gt;
                          &lt;ListItem&gt;
                              &lt;Text&gt;buscar por género&lt;/Text&gt;
                          &lt;/ListItem&gt;
                          &lt;ListItem onPress={() =&gt; Actions.profile({ 
                          name: userName, 
                          lastname: userLastname, 
                          email: userEmail, 
                          bio: userBio, 
                          avatar: avatarUrl })}
                          &gt;
                              &lt;Text&gt;Perfil&lt;/Text&gt;
                          &lt;/ListItem&gt;
                          &lt;ListItem onPress={() =&gt; Actions.auth()}&gt;
                              &lt;Text&gt;Cerrar sesión&lt;/Text&gt;
                          &lt;/ListItem&gt;
                      &lt;/List&gt;
                  &lt;/Content&gt;
              &lt;/View&gt;
          &lt;/View&gt;
      );
  }
  }
  
  export default Menu;
  </code></pre>
  
  <p>The one in my Profile.js is not: (see renderAvatar function)</p>
  
  <pre><code>import React, { Component } from 'react';
  import _ from 'lodash';
  import { 
  View, 
  Text, 
  StyleSheet, 
  TouchableOpacity,
  Image, 
  TextInput,
  Platform,
  ToastAndroid, 
  Dimensions,
  ScrollView,
  Thumbnail
  }   from 'react-native';
  
  import ImagePicker from 'react-native-image-picker';
  import firebase from 'firebase';
  import RNFetchBlob from 'react-native-fetch-blob';
  import Helpers from '../../lib/helpers';
  import Avatar from '../../img/avatar.png';
  
  const ITEM_WIDTH = Dimensions.get('window').width;
  
  const Blob = RNFetchBlob.polyfill.Blob;
  const fs = RNFetchBlob.fs;
  window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
  window.Blob = Blob;
  
  
  const uploadImage = (uri, imageName, mime = 'image/jpg') =&gt; {
  return new Promise((resolve, reject) =&gt; {
      const uploadUri = Platform.OS === 'ios' ? uri.replace('file://', '') : uri;
      let uploadBlob = null;
      const imageRef = firebase.storage().ref('images').child(imageName);
      fs.readFile(uploadUri, 'base64')
          .then((data) =&gt; {
              return Blob.build(data, { type: `${mime};BASE64` });
          })
          .then((blob) =&gt; {
              uploadBlob = blob;
              return imageRef.put(blob, { contentType: mime });
          })
          .then(() =&gt; {
              uploadBlob.close();
              return imageRef.getDownloadURL();
          })
          .then((url) =&gt; {
              resolve(url);
          })
          .catch((error) =&gt; {
              reject(error);
          });
  });
  };
  
  
  class Profile extends Component {
  constructor(props) {
      super(props);
      this.state = {
          imagePath: '',
          name: this.props.avatar !== 'profile' ? this.props.name : '',
          lastname: this.props.avatar !== 'profile' ? this.props.lastname : '',
          email: this.props.avatar !== 'profile' ? this.props.email : '',
          bio: this.props.avatar !== 'profile' ? this.props.bio : '', 
          uid: ''    
      };
  }
  
  async componentWillMount() {
      try {
          const { currentUser } = await firebase.auth();
          this.setState({
              uid: currentUser.uid
          });
      } catch (error) {
          console.log(error);
      }
  }
  
  openImagePicker() {
      const options = {
          title: 'Seleccione avatar',
          storageOptions: {
              skipBackup: true,
              path: 'images'
          }
      };
  
      ImagePicker.showImagePicker(options, (response) =&gt; {
          if (response.didCancel) {
              console.log('User canceled image Picker');
          } else if (response.error) {
              console.log('Error' + response.error);
          } else if (response.customButton) {
              console.log('User tapped custom button' + response.customButton);
          } else {
              this.setState({ 
                  imagePath: response.uri,
                  imageHeight: response.height,
                  imageWidth: response.width
              });
          }
      });
  }
  
  saveForm() {
      const { name, lastname, email, bio, uid, imagePath } = this.state;
      if (uid) {
          try {
              name ? Helpers.setUserName(uid, name) : null;
              bio ? Helpers.setUserBio(uid, bio) : null;
              email ? Helpers.setUserEmail(uid, email) : null;
              lastname ? Helpers.setUserLastname(uid, lastname) : null;
              imagePath ? 
                  uploadImage(imagePath, `${uid}.jpg`)
                  .then((responseData) =&gt; {
                      Helpers.setImageUrl(uid, responseData);
                  })
                  .done()
              : null;
  
              toastMessage('¡Tu datos han sido actualizados!');
          } catch (error) {
              console.log(error);
          }
      }  
  }
  
  renderAvatar() {
      console.log(this.props.avatar);
      if (this.props.avatar !== null) {
          return (&lt;Image 
          style={{ width: 100, height: 100, borderRadius: 150 / 2 }}
          source={{ uri: this.props.avatar }}
          /&gt;);
      } 
      return (&lt;Image 
          style={{ width: 100, height: 100, borderRadius: 150 / 2 }}
          source={Avatar}
      /&gt;); 
  }
  
  render() {
      return (
          &lt;ScrollView contentContainerStyle={{ alignItems: 'center' }} style={styles.container}&gt;
              &lt;TouchableOpacity
                  onPress={this.openImagePicker.bind(this)}
                  style={{ marginBottom: 40, marginTop: 20 }}
              &gt;
                  &lt;View style={{ alignItems: 'center' }}&gt;
                      {this.renderAvatar()}
                      &lt;Text style={{ color: 'white' }}&gt;Avatar &lt;/Text&gt;
                  &lt;/View&gt;
              &lt;/TouchableOpacity&gt;
              &lt;TextInput
                  underlineColorAndroid='rgba(0,0,0,0)'
                  selectionColor="#fff"
                  placeholderTextColor="#ffffff"
                  autoCorrect={false} //we disable the autocorrect from ios or android
                  style={styles.textInput}
                  placeholder='nombres'
                  value={this.state.name}
                  onChangeText={(name) =&gt; this.setState({ name })}
              /&gt;
              &lt;TextInput
                  underlineColorAndroid='rgba(0,0,0,0)'
                  selectionColor="#fff"
                  placeholderTextColor="#ffffff"
                  autoCorrect={false} //we disable the autocorrect from ios or android
                  style={styles.textInput}
                  placeholder='apellidos'
                  value={this.state.lastname}
                  onChangeText={(lastname) =&gt; this.setState({ lastname })}
              /&gt;
              &lt;TextInput
                  underlineColorAndroid='rgba(0,0,0,0)'
                  selectionColor="#fff"
                  placeholderTextColor="#ffffff"
                  autoCorrect={false} //we disable the autocorrect from ios or android
                  style={styles.textInput}
                  type='email-address'
                  placeholder='email@gmail.com'
                  keyboardType="email-address"
                  autoCapitalize="none"
                  value={this.state.email}
                  onChangeText={(email) =&gt; this.setState({ email })}
  
              /&gt;
              &lt;TextInput
                  multiline={true}
                  numberOfLines={10}
                  underlineColorAndroid='rgba(0,0,0,0)'
                  selectionColor="#fff"
                  placeholderTextColor="#ffffff"
                  autoCorrect={false} //we disable the autocorrect from ios or android
                  style={styles.textArea}
                  placeholder='Ingresa algo sobre tí'
                  value={this.state.bio}
                  onChangeText={(bio) =&gt; this.setState({ bio })}
              /&gt;
  
              &lt;TouchableOpacity
                  style={styles.buttonStyle}
                  onPress={this.saveForm.bind(this)}
              &gt;
                  &lt;Text style={styles.buttonText}&gt;Guardar&lt;/Text&gt;
              &lt;/TouchableOpacity&gt;
          &lt;/ScrollView&gt;
      );
  }
  }
  
  const styles = StyleSheet.create({
  container: {
      flex: 1, 
      backgroundColor: '#0277BD',
  },
  textInput: {
      height: 40,
      borderWidth: 1,
      borderColor: '#cecece',
      marginBottom: 20,
      borderRadius: 20,
      paddingHorizontal: 20,
      marginHorizontal: 50,
      backgroundColor: 'rgba(255, 255, 255, 0.3)',
      color: '#ffffff',
      width: ITEM_WIDTH - 100,
  },
  buttonStyle: {
      justifyContent: 'center',
      alignItems: 'center',
      borderWidth: 1,
      borderColor: '#ccc',
      borderRadius: 20,
      paddingVertical: 10,
      width: 100,
      backgroundColor: '#2D09A1',
      marginHorizontal: 20,
      marginTop: 20,
      marginBottom: 20
  },
  buttonText: {
      color: 'white',
      fontSize: 16,
      fontWeight: '600',
  },
  textArea: {
      height: 150,
      justifyContent: 'flex-start',
      textAlignVertical: 'top',
      borderWidth: 1,
      borderColor: '#cecece',
      marginBottom: 20,
      borderRadius: 20,
      paddingHorizontal: 16,
      backgroundColor: 'rgba(255, 255, 255, 0.3)',
      color: '#ffffff',
      width: ITEM_WIDTH - 150,
  }
  });
  
  const toastMessage = (texto) =&gt; {
  ToastAndroid.showWithGravity(
      texto,
      ToastAndroid.SHORT,
      ToastAndroid.CENTER
  );
  };
  
  export default Profile;
  </code></pre>
  
  <p>The problem is in the renderAvatar method: I have defined the method in the same way that I did in the Menu.js and called it in the return the same way I did in the Menu.js and used the same image path as in the Menu.js, and both the Menu.js and Profile.js are located in the same directory. But I get the following error: 'uri should not be an empty string'.</p>
  
  <p>When I just return:</p>
  
  <pre><code> render() {
      return (
          &lt;ScrollView contentContainerStyle={{ alignItems: 'center' }} style={styles.container}&gt;
              &lt;TouchableOpacity
                  onPress={this.openImagePicker.bind(this)}
                  style={{ marginBottom: 40, marginTop: 20 }}
              &gt;
                  &lt;View style={{ alignItems: 'center' }}&gt;
                  &lt;Image 
                      style={{ width: 100, height: 100, borderRadius: 150 / 2 }}
                      source={Avatar}
                  /&gt; ...
  </code></pre>
  
  <p>in my Profile.js the default avatar image displays correctly. I don't get this. I don't get the logic of this. If anybody can help me I would appreciate it. Thanks.</p>