All requests using the firebase cloud storage sdk result in a "no objects exists with the desired reference". The same code built with expo and react native runs perfectly well on a friend's machine.Other firebase services seem to work, such as firestore and firebase cloud messaging. This is the hook used to invoke the firebase uploadfile request:
import { useState } from "react";
import { UseMutateFunction, useMutation } from "@tanstack/react-query";
import { ImagePickerAsset } from "expo-image-picker";
import storage from "@/storage/init";
type uploadFileResult = {
uploadFile: UseMutateFunction<
string | undefined,
Error,
uploadFileArgs,
unknown
>;
uploadProgress: number;
isUploading: boolean;
error: Error | null;
downloadURL: string | null;
};
type uploadFileArgs = { file: ImagePickerAsset };
//Handles file upload to Firebase storage.
export function useUploadFile(): uploadFileResult {
const [uploadProgress, setUploadProgress] = useState(0);
const [downloadURL, setDownloadURL] = useState<string | null>(null);
const uploadFile = async (props: uploadFileArgs) => {
const localFilePath = props.file.uri;
console.info(localFilePath);
if (!localFilePath) return;
const reference = storage.ref(`${props.file.fileName}`);
const task = reference.putFile(localFilePath);
task.on("state_changed", (taskSnapshot) => {
setUploadProgress(
(taskSnapshot.bytesTransferred / taskSnapshot.totalBytes) * 100,
);
});
await task;
const url = await reference.getDownloadURL();
setDownloadURL(url);
return url;
};
const {
mutate,
isPending: isUploading,
error,
} = useMutation({
mutationFn: uploadFile,
});
return {
uploadFile: mutate,
uploadProgress,
isUploading,
error,
downloadURL,
};
}
This is the implementation of said hook:
import { SettingsToolbar } from "@/components/screens/settings/Toolbar";
import { Avatar } from "@/components/ui/Avatar";
import { Button } from "@/components/ui/Button";
import { Input, InputBox, InputLabel } from "@/components/ui/Input";
import { Tags } from "@/components/ui/Tags";
import { ToastType } from "@/components/ui/Toast";
import { UserRepo } from "@/db/user";
import { useTheme } from "@/hooks/useTheme";
import { trimAll } from "@/lib/utils";
import { Gender } from "@/models/models";
import { useShowToast } from "@/providers/toastProvider";
import { useUserContext } from "@/providers/userProvider";
import { Timestamp } from "@react-native-firebase/firestore";
import * as ImagePicker from "expo-image-picker";
import { router } from "expo-router";
import { Pencil } from "lucide-react-native";
import { useCallback, useState } from "react";
import {
KeyboardAvoidingView,
Pressable,
ScrollView,
View,
} from "react-native";
import { GenderSelect, InterestedInSelect } from "./signup";
import { useUploadFile } from "@/hooks/useFileUpload";
export default function Settings() {
const theme = useTheme();
const user = useUserContext();
const showToast = useShowToast();
const { uploadFile, downloadURL } = useUploadFile();
const [avatar, setAvatar] = useState(user?.avatar || "");
const [username, setUsername] = useState(user?.username || "");
const [gender, setGender] = useState<Gender>(user?.gender || "male");
const [lookingFor, setLookingFor] = useState(user?.lookingFor[0] || "female");
const [tags, setTags] = useState<string[]>(
user?.tags.filter((v) => v !== user.gender) || [],
);
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: [1, 1],
quality: 1,
});
if (!result.canceled) {
setAvatar(result.assets[0].uri);
uploadFile({ file: result.assets[0] });
return;
}
showToast("Image upload was cancelled", ToastType.WARNING);
};
const updateUser = useCallback(() => {
try {
if (username.length < 3) {
throw Error("Username is too short!");
}
if (trimAll(username) !== username) {
throw Error("Username has incorrect format!");
}
if (username.length > 20) {
throw Error("Username is too long!");
}
if (user) {
const userRepo = new UserRepo(user.id);
//user.avatar = avatar;
user.username = username;
user.gender = gender;
user.tags = [gender, ...tags];
user.lookingFor = [lookingFor, ...tags];
user.lastOnline = Timestamp.now();
if (downloadURL) {
user.avatar = downloadURL;
}
userRepo
.updateUser(user)
.then(() => {
router.back();
showToast("Settings updated", ToastType.INFO);
})
.catch((r) => {
console.error(r);
showToast("Error updating settings", ToastType.ERROR);
});
}
} catch (r) {
{
console.warn(r);
showToast(`${r}`, ToastType.WARNING);
}
}
}, [downloadURL, gender, lookingFor, showToast, tags, user, username]);
return (
<KeyboardAvoidingView
style={{ flex: 1, backgroundColor: theme.background }}
>
<SettingsToolbar />
<ScrollView style={{ flex: 1 }}>
<View
style={{
paddingHorizontal: 42,
marginTop: 40,
alignItems: "center",
}}
>
<Pressable onPress={pickImage}>
<Avatar size={128} src={avatar} />
<Pencil
style={{ position: "absolute", bottom: 0, end: 0 }}
color={theme.onSecondary}
/>
</Pressable>
</View>
<View style={{ alignItems: "center", gap: 8, marginBottom: 40 }}>
<Input>
<InputLabel style={{ color: theme.text }}>Username</InputLabel>
<InputBox
maxLength={20}
value={username}
onChangeText={setUsername}
/>
</Input>
<GenderSelect gender={gender} onChange={setGender} />
<InterestedInSelect gender={lookingFor} onChange={setLookingFor} />
<Tags tags={tags} setTags={setTags} />
<Button onPress={updateUser}>Save</Button>
</View>
</ScrollView>
</KeyboardAvoidingView>
);
}
Again, this issue only seems to persist on my machine with my emulator/phone. After some debugging I also found out that I'm unable to even list the items in the default bucket. I get the same error. That leads me to believe that maybe the reference that "doesn't" exist is the default reference of the bucket itself? Any ideas on what could be a possible problem ? Thank you for your assistance in advance.
Okay, for some reason firebase was not able to find the default bucket. So every time that I tried to put a file into the storage (which I had initiated as storage()
) It resulted in a "No object reference exists..." Which just meant that the bucket could not be found... So what I did to fix it is to initialize the storage as if it is a custom bucket:
import { firebase } from "@react-native-firebase/storage";
const storage = firebase.app().storage(process.env.BUCKET_URL);
export default storage;
Still I have no idea why it can't find the default bucket...