Reputation: 11
I'm working on a React Native project where I need to upload an image to Firebase. I'm using react-native-image-picker for image selection and @react-native-firebase/firestore for interacting with Firestore. The form works well, and the text fields store data in Firebase correctly, but the image field in Firebase shows null.
I am receiving an error when I try to upload the image after clicking the "Select Image" button. The image URI is not stored in Firestore, and instead, it shows null. Please see the provided screenshots!
Steps to reproduce:
Click on the "Select Image" button.
Pick an image from the device.
Click on the "Submit" button.
Expected behavior: The image URI should be saved in Firestore along with the other ticket data.
Actual behavior: An error occurs when I click the select button, and the image URI is not uploaded to Firestore; it shows null instead.
Environment:
React Native version: 0.74.1
react-native-image-picker version: 7.1.2
@react-native-firebase/firestore version: 20.1.0
Code is below -
// Importing necessary libraries
import React, { useEffect, useState } from "react";
import { View, Text, StyleSheet, TouchableOpacity, Image, Alert, TextInput } from "react-native";
import ImagePicker from "react-native-image-picker";
import { firebase } from "@react-native-firebase/firestore";
// Importing firebaseConfig for Firestore
import { firestore } from "../firebaseConfig";
// Defining NewTicket component
export default function NewTicket({ route, navigation }) {
// Destructuring parameters from route
const { uid, phoneNumber } = route.params;
// State variables
const [ticketData, setTicketData] = useState("");
const [image, setImage] = useState(null);
const [users, setUsers] = useState([]);
// Firestore reference
const todoRef = firebase.firestore().collection("users");
// Fetching data useEffect hook
useEffect(() => {
const fetchData = async () => {
const querySnapshot = await todoRef.where("phoneNumber", "==", phoneNumber).get();
const fetchedUsers = [];
querySnapshot.forEach((doc) => {
const { name, phoneNumber, designation, usertype } = doc.data();
fetchedUsers.push({
id: doc.id,
name: name || "",
phoneNumber: phoneNumber || "",
designation: designation || "",
usertype: usertype || "",
});
});
setUsers(fetchedUsers.length > 0 ? fetchedUsers : [{ id: "0", name: "", phoneNumber: "", designation: "", usertype: "" }]);
};
fetchData();
}, [phoneNumber]);
// Input handler function
const handleInput = (text) => {
setTicketData(text);
};
// Image selection function
const selectImage = () => {
console.log("select image");
const options = {
title: "Select Image",
storageOptions: {
skipBackup: true,
path: "images",
},
};
ImagePicker.showImagePicker(options, (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.uri };
setImage(source);
}
});
};
// Submit function
const submit = async () => {
try {
const user = users[0];
await firestore()
.collection("ticketData")
.doc()
.set({
ticketData,
name: user.name,
imageUri: image ? image.uri : null,
});
console.log("submitted");
Alert.alert(
"Submitted",
"Your ticket has been submitted successfully!",
[
{
text: "OK",
onPress: () => navigation.goBack(),
},
],
{ cancelable: false }
);
} catch (error) {
console.error("Error saving details: ", error);
}
};
// Return JSX
return (
<View style={styles.main}>
<Image source={require("../assets/assetsApp/impressions_logo.webp")} style={styles.image} />
<Text style={styles.formHeadingText}>New Ticket Page</Text>
<Text style={styles.belowHeading}>Fill your basic details to complete your ticket</Text>
<View>
<TextInput style={styles.formInput} placeholder="Enter ticket name" value={ticketData} onChangeText={handleInput} />
<TouchableOpacity onPress={selectImage} style={styles.selectButton}>
<Text style={styles.textSelectButton}>Select Image</Text>
</TouchableOpacity>
{image && <Image source={image} style={{ width: 200, height: 200, marginTop: 10 }} />}
<TouchableOpacity onPress={submit} style={styles.submitButton}>
<Text style={styles.textSubmitButton}>Submit</Text>
</TouchableOpacity>
</View>
</View>
);
}
Any help would be appreciated. Thanks!
PACKAGE.JSON FILE CODE --
{
"name": "my-app",
"version": "1.0.0",
"main": "expo/AppEntry.js",
"scripts": {
"start": "expo start --dev-client",
"android": "expo run:android",
"ios": "expo run:ios",
"web": "expo start --web"
},
"dependencies": {
"@expo/metro-runtime": "~3.2.1",
"@expo/vector-icons": "^14.0.0",
"@react-native-firebase/app": "^20.1.0",
"@react-native-firebase/auth": "^20.1.0",
"@react-native-firebase/firestore": "^20.1.0",
"@react-native-firebase/storage": "^20.1.0",
"@react-native-masked-view/masked-view": "0.3.1",
"@react-navigation/native": "^6.1.17",
"@react-navigation/native-stack": "^6.9.26",
"@react-navigation/stack": "^6.3.29",
"expo": "^51.0.14",
"expo-dev-client": "~4.0.15",
"expo-image-picker": "~15.0.5",
"expo-permissions": "^14.4.0",
"expo-status-bar": "~1.12.1",
"firebase": "^10.12.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.74.1",
"react-native-gesture-handler": "~2.16.1",
"react-native-image-picker": "^7.1.2",
"react-native-paper": "^5.12.3",
"react-native-safe-area-context": "^4.10.1",
"react-native-screens": "^3.31.1",
"react-native-web": "~0.19.10",
"typescript": "~5.3.3"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@types/react-native": "^0.73.0"
},
"private": true
}
Upvotes: 0
Views: 34