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