3

I am building a react native multiuser app and I am trying to set up the user profile page. I am trying to make a user profile picture that a user can upload from their image library. I manage to open the image gallery but when I select an image I get "[Unhandled promise rejection: Error: Failed to write data to a file] at node_modules/react-native/Libraries/BatchedBridge/NativeModules.js:106:50 in promiseMethodWrapper at node_modules/expo-modules-core/build/NativeModulesProxy.native.js:15:23 in moduleName.methodInfo.name at node_modules/expo-image-picker/build/ImagePicker.js:164:17 in launchImageLibraryAsync at node_modules/expo-image-picker/build/ImagePicker.js:160:7 in launchImageLibraryAsync at components/profile.js:245:23 in showImagePicker"

here's my code:

import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View, FlatList, Image, Button, Pressable, ScrollView  } from 'react-native';
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';
import { faStar } from '@fortawesome/free-solid-svg-icons'
import React, {useState, useEffect, useCallback} from 'react'
import { TextInput } from 'react-native-gesture-handler';
import AsyncStorage from '@react-native-async-storage/async-storage';
import RNPickerSelect from 'react-native-picker-select';
import * as ImagePicker from 'expo-image-picker';



export default function Profile(props) {

    let countries = [
    //countries
  ]


  const [ username, setUsername ] = useState("")
  const [ password, setPassword ] = useState("")
  const [ confpassword, setConfpassword ] = useState("")
  const [ email, setEmail ] = useState("")
  const [ gender, setGender ] = useState("")
  const [ dob, setDob ] = useState("")
  const [ hobbies, setHobbies ] = useState("")
  const [ orgin, setOrgin ] = useState("") 
  const [ lives, setLives ] = useState("")
  const [ bio, setBio ] = useState("")
  const message = props.navigation.getParam("message", null)
  const [ profileImage, setProfileImage ] = useState(null)

  const showImagePicker = async () => {
    // Ask the user for the permission to access the media library 
    const permissionResult = await ImagePicker.requestMediaLibraryPermissionsAsync();

    if (permissionResult.granted === false) {
      alert("You've refused to allow this appp to access your photos!");
      return;
    }

    const result = await ImagePicker.launchImageLibraryAsync();

    // Explore the result
    console.log(result);

    if (!result.cancelled) {
      setProfileImage(result.uri);
      console.log(result.uri);
    }
  }

  const openCamera = async () => {
    // Ask the user for the permission to access the camera
    const permissionResult = await ImagePicker.requestCameraPermissionsAsync();

    if (permissionResult.granted === false) {
      alert("You've refused to allow this appp to access your camera!");
      return;
    }

    const result = await ImagePicker.launchCameraAsync();

    // Explore the result
    console.log(result);

    if (!result.cancelled) {
      setProfileImage(result.uri);
      console.log(result.uri);
    }
  }



  



  return (
    <View style={styles.container}>
      <ScrollView style={styles.scroll} >
      <Button onPress={showImagePicker} title="Select an image" />

      <View style={styles.imageContainer}>
        {
          profileImage !== '' && <Image
            source={{ uri: profileImage }}
            style={styles.image}
          />
        }
      </View>

      <Text style={styles.label}>
        Email: 
      </Text>
      <TextInput style={styles.input} placeholder="Email" 
        onChangeText={ text => setEmail(text)} value={email} />
      
      <Text style={styles.label}>Bio:</Text>
      <TextInput style={styles.input} placeholder="Bio" onChangeText={ text => setBio(text)}
        value={bio}
      />
        <Text style={styles.label}></Text>
       <RNPickerSelect 
            onValueChange={(value) => setOrgin(value)}
            value={orgin}
            useNativeAndroidPickerStyle={false}
            items={countries} placeholder={{label: "Country of Orgin", value: null}} style={pickerSelectStyles}
        />

        <Text style={styles.label}></Text>
        <RNPickerSelect 
            onValueChange={(value) => setLives(value)}
            value={lives}
            useNativeAndroidPickerStyle={false}
            items={countries} placeholder={{label: "Currently living...", value: null}} style={pickerSelectStyles}
        />

      
      <Text style={styles.error}> {message}</Text>

      <Button onPress={ () => profile()} title="SetUp Profile"></Button>
      </ScrollView>
      <View style={styles.footer}>
        
      </View>
      <StatusBar style="auto"/>
    </View>


  )


}

Profile.navigationOptions = screenProps => ({
    headerLeft: () => null,
    gestureEnabled: false,
    headerStyle: {
      backgroundColor: 'black'
    },
    headerTintColor: 'white',
  
  })

const styles = StyleSheet.create({
    container: {
      flex: 1, 
      backgroundColor: '#999',
      
    },
    
    scroll: {
      backgroundColor:'black'
    },
  
    footer: {
      backgroundColor: 'black',
      padding:35,
    },
  
    label: {
      fontSize: 24,
      color: "white",
      padding: 10,
  
    },
  
    input: {
      fontSize: 24,
      backgroundColor: "white",
      padding: 10,
      margin: 10,
      borderRadius: 5,
    },
    buttonContainer: {
      width: 400,
      flexDirection: 'row',
      justifyContent: 'space-around'
    },
    imageContainer: {
      padding: 30
    },
    image: {
      width: 400,
      height: 300,
      resizeMode: 'cover'
    },

    
  
  
    
  });
  
  const pickerSelectStyles = StyleSheet.create({
      inputIOS: {
          fontSize: 16,
          paddingVertical: 12,
          paddingHorizontal: 10,
          borderWidth: 1,
          borderColor: 'gray',
          borderRadius: 4,
          color: 'white',
          paddingRight: 30 // to ensure the text is never behind the icon
      },
      inputAndroid: {
          fontSize: 16,
          paddingHorizontal: 10,
          paddingVertical: 8,
          borderWidth: 0.5,
          borderColor: 'purple',
          borderRadius: 8,
          color: 'white',
          paddingRight: 30 // to ensure the text is never behind the icon
      }
  });

how can I solve this issue?

Itay Lador
  • 313
  • 1
  • 10
  • Had a similar issue, i realized expo caches the selected image or video so you need twice the storage space for it to be successful. You are probably working with large files and running out of storage space e.g if you select a 1GB file expo needs another 1GB to cache the file totaling 2GB for the operation to be successful. I ended up checking available device space with FileSystem and limiting selected filesize. you can also clear expo app cache on your mobile device. – chidimez Aug 24 '22 at 07:40

1 Answers1

1

This is how you should access phone's library.

const [image, setImage] = useState(null);

 const pickImage = async () => {
   // No permissions request is necessary for launching the image library
   let result = await ImagePicker.launchImageLibraryAsync({
     mediaTypes: ImagePicker.MediaTypeOptions.All,
     allowsEditing: true,
     aspect: [4, 3],
     quality: 1,
   });

   console.log(result);

   if (!result.cancelled) {
     setImage(result.uri);
   }
 };
G-T
  • 111
  • 6