When I pick an image using react-native-image-picker everything works as expected. I then pass the response to a function to upload the image to firebase storage.
On my device, this seems to work, but then I get the following error:
Possible Unhandled Promise Rejection (id: 0):
TypeError: null is not an object (evaluating 'image.uri')
If I repeat the steps again, the first image will then upload successfully.
I believe I need to get the second function to wait for the first function to complete the setImage(source) part and the error is coming from the { uri } = image
line not yet having the required data before trying to upload.
const ProfilePicChange = () => {
useEffect(() => {
if (isFocused) getUserData();
}, [isFocused]);
const isFocused = useIsFocused();
const navigation = useNavigation();
const [menuVisible, setMenuVisible] = useState(false);
const [userId, setUserId] = useState("");
const [email, setEmail] = useState("");
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [uploading, setUploading] = useState(false);
const [transferred, setTransferred] = useState(0);
const [image, setImage] = useState(null);
const [debug, setDebug] = useState(false);
const ImageTapped = () => {
setMenuVisible(!menuVisible);
};
const getUserData = async () => {
let email = await AsyncStorage.getItem("email");
if (email !== null) {
firestore()
.collection("users")
.where("email", "==", email.toLowerCase())
.onSnapshot((querySnapshot) => {
querySnapshot.forEach((doc) => {
setUserId(doc.data()?.uid);
setFirstName(doc.data().firstName);
setLastName(doc.data().lastName);
});
});
} else {
}
};
const onTakePhoto = async () => {
const options = {
maxWidth: 2000,
maxHeight: 2000,
cameraType: "front",
storageOptions: {
skipBackup: true,
path: "images",
},
};
launchCamera(options, (response) => {
console.log("Response = ", response);
if (response.didCancel) {
console.log("User cancelled image picker");
} else if (response.error) {
console.log("ImagePicker Error: ", response.error);
} else {
const source = { uri: response.assets[0].uri };
console.log(source);
setImage(source);
}
});
uploadImage();
};
const onSelectImagePress = async () => {
const options = {
maxWidth: 2000,
maxHeight: 2000,
storageOptions: {
skipBackup: true,
path: "images",
},
};
launchImageLibrary(options, (response) => {
console.log("Response = ", response);
if (response.didCancel) {
console.log("User cancelled image picker");
} else if (response.error) {
console.log("ImagePicker Error: ", response.error);
} else if (response.customButton) {
console.log("User tapped custom button: ", response.customButton);
} else {
const source = { uri: response.assets[0].uri };
const uriSource = { uri: response.assets[0] };
console.log(source);
setImage(source);
}
});
uploadImage();
};
const uploadImage = async () => {
const { uri } = image;
const filename = userId;
const uploadUri = Platform.OS === "ios" ? uri.replace("file://", "") : uri;
setDebug(true);
setUploading(true);
setTransferred(0);
const task = storage().ref(filename).putFile(uploadUri);
// set progress state
task.on("state_changed", (snapshot) => {
setTransferred(
Math.round(snapshot.bytesTransferred / snapshot.totalBytes) * 10000
);
});
try {
await task;
} catch (e) {
console.error(e);
}
setUploading(false);
Alert.alert(
"Photo uploaded!",
"Your photo has been uploaded to Firebase Cloud Storage!"
);
setImage(null);
};
return (
<>
<View style={{ backgroundColor: "#ffffff" }}>
<ScrollView>
<View
style={{
backgroundColor: "#ffffff",
paddingTop: 20,
paddingBottom: 1000,
}}
>
<BackButton />
<View style={{ paddingTop: 50, paddingHorizontal: 25 }}>
<TouchableOpacity onPress={ImageTapped}>
<View style={{ backgroundColor: "#ffffff", paddingTop: 0 }}>
<Image
source={defaultProfile}
style={styles.defaultProfile}
/>
</View>
</TouchableOpacity>
<Text
style={[
styles.subHeading,
{ textAlign: "center", fontSize: 32, color: "#540d6e" },
]}
>
{firstName} {lastName}
</Text>
<View style={{ paddingHorizontal: 40, paddingTop: 20 }}>
<Button
buttonStyle={[
styles.buttonStyle2,
{ borderColor: "#ef4166", marginBottom: 5 },
]}
titleStyle={[
styles.titleStyle2,
{
color: "#ef4166",
fontFamily: "RifficFree-Bold",
fontSize: 14,
},
]}
type="outline"
title="Open Camera"
onPress={onTakePhoto}
/>
<Button
buttonStyle={[
styles.buttonStyle2,
{ borderColor: "#ef4166", marginBottom: 5 },
]}
titleStyle={[
styles.titleStyle2,
{
color: "#ef4166",
fontFamily: "RifficFree-Bold",
fontSize: 14,
},
]}
type="outline"
title="Browse Pictures"
onPress={onSelectImagePress}
/>
<Button
buttonStyle={[
styles.buttonStyle2,
{ borderColor: "#ef4166", marginBottom: 5 },
]}
titleStyle={[
styles.titleStyle2,
{
color: "#ef4166",
fontFamily: "RifficFree-Bold",
fontSize: 14,
},
]}
type="outline"
title="Nah, I look good!"
onPress={() => navigation.goBack()}
/>
<Text>
User is {userId}
</Text>
{debug ? <Text>This fired!</Text> : <Text>WAITING!</Text>}
</View>
</View>
</View>
</ScrollView>
</View>
</>
);
};
export default ProfilePicChange;