Search code examples
javascriptreact-nativeexpoimagepickerreact-native-image-picker

Expo-image-picker: "Unhandled promise rejection: Error: Failed to write data to a file"


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?


Solution

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