Firestore (Web version 9 modular): getDocsFromCache seems not working - javascript

I'm new to Firebase and I found getDocsFromCache. I heard that firebase updated it's version to version 9, (modular) and i have to use more than just query.get({source: "cache"}). But getDocsFromCache didn't work for me. Every time i call getDocsFromCache, it does not throw any errors but snapshot.empty is always true so i can't access to my documents(collection).
If i have to cache manually, how? If not, what am i missing?
Thank you.
import {
​collection,
​getDocs,
​getDocsFromCache,
​query,
} from 'firebase/firestore';
import { db } from '../firebase-config';
export const getReviews = async () => {
​const q = query(collection(db, 'review'));
​try {
​const snapshot = await getDocsFromCache(q);
​console.log(snapshot.empty); // always true but not throwing any error
​snapshot.forEach((doc) => {
​/* ... */
​});
​} catch (e) {
// never reach here
​const snapshot = await getDocs(q);
/* ... */
​}
};

From the documentation on configuring offline persistence:
For the web, offline persistence is disabled by default. To enable persistence, call the enablePersistence method.
So make sure to enable the cache by calling this right after initializing Firebase and Firestore:
import { enableIndexedDbPersistence } from "firebase/firestore";
enableIndexedDbPersistence(db);

Related

Transaction failure while testing firebase firestore

I am trying to write some tests for the cloud functions I have written, but I am facing a problem where a transaction never succeeds and ends up in an error:
9 FAILED_PRECONDITION: the stored version (1648901730789554) does not match the required base version (0)
Problematic code is the following:
await firebase.db().runTransaction((t) => {
return t.get(docRef).then((doc) => {
if (!doc.exists) {
console.log("no exist");
}
});
});
It is run several times (checked with debugger), and then the error messages is thrown...
And the firebase test env init:
export async function initialize() {
fb.initializeTestApp({
projectId: "my-test-project",
auth: { uid: "alice", email: "alice#example.com" }
});
const testEnv = await initializeTestEnvironment({
projectId: "demo-project-1234",
firestore: {
rules: fs.readFileSync("../firestore.rules", "utf8"), // Load rules from file
// host and port can be omitted if they can be discovered from the hub.
},
});
const alice = testEnv.authenticatedContext(uid);
const db = (alice.firestore() as unknown) as firestore.Firestore;
firebase.db = () => db;
return testEnv;
}
Am I doing something wrong?
Note: I currently have only one test that runs, nothing else. And firebase emulators are running, without any other app accessing it.
After some more research, I have figured out that I was mixing #firebase/testing and firebase-admin, and the matter should not be used for unit testing backend functions according to this post.
On a side note, it seems there already is a function to create a doc iff it does not exist:
docRef.create(...).then(() => log("ok")).catch(() => log("Not ok"))

"query is not a function" Next Js getServerSideprops and firebase error

I'm using NextJS and firebase as my primary database for the app that I'm currently building for an NGO. and I ran into an issue.
import {
collection,
where,
query,
getDocs
} from '#firebase/firestore';
import { db } from '../../../services/firebase';
export async function getServerSideProps({query}) {
const user = await getDocs(query(collection(db, 'members'), where('id', '==', query)))
return {
props: {
// VisionInfo: JSON.stringify(user.docs.map(item => item.data()))
json: JSON.stringify('Hello')
}
};
}
The only way to get Query from the URL in NextJS in serverSideProps is to use the keyword "query" but the same keyword is used to fetch firebase document.
The error shows "query is not a function"
Is there anyway I could get Query into serversideprops ?
The issue arises because you also have "query" in getServerSideProps parameters. Try naming the import from Firestore SDK (or the query param) as shown below:
import { query as fireQuery } from '#firebase/firestore';
export async function getServerSideProps({query}) {
const user = await getDocs(fireQuery(collection(db, 'members'), where('id', '==', query)))
// use fireQuery here ^^^
})

verifyIdToken method doesn't exist in Auth type using getAuth from firebase/auth

I'm trying to follow the example given here where it shows the following example to verify an ID token:
// idToken comes from the client app
getAuth()
.verifyIdToken(idToken)
.then((decodedToken) => {
const uid = decodedToken.uid;
// ...
})
.catch((error) => {
// Handle error
});
My code looks like this:
function createFirebaseAdminApp(config: AppOptions) {
if (getApps().length === 0) {
return initializeApp(config);
} else {
return getApp();
}
}
const options: AppOptions = {
credential: cert({
projectId: process.env.FIREBASE_PROJECT_ID,
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
privateKey:
process.env.FIREBASE_PRIVATE_KEY != undefined
? process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, "\n")
: "",
}),
databaseURL: process.env.FIREBASE_DATABASE_URL,
};
const firebaseAdmin = createFirebaseAdminApp(options) as FirebaseApp;
const adminAuth = getAuth(firebaseAdmin);
adminAuth
.verifyIdToken(token)
.then((decodedToken) => {
res.locals.decodedToken = decodedToken;
next();
})
.catch(() => {
next(new HttpError("Invalid token provided", 403));
});
But I keep getting
Property 'verifyIdToken' does not exist on type 'Auth'
I have the latest version of the firebase package, which I assume the example given by the docs is using considering it uses getAuth, so can't tell what I'm doing wrong. Also I'm trying to avoid mixing firebase-admin and firebase, not sure if this is correct, but if I mixed them I can't seem to avoid having to initialize too App instances.
Thanks for any help!
You are mixing up the Admin SDK and the client SDK.
The documentation you linked is for the Admin SDK only. Notice how it is organized in the section for Admin. It is not using getAuth anywhere in that page. The Admin SDK is initialized completely differently than the client SDK, and it does not work at all in browsers. It runs on secure backens only.
The client SDK that you're using doesn't have a function for verifying tokens. That is for secure backends only using the Adminn SDK.

weird behavior await running without async

I was running firebase when I saw a strange behavior which I am unable to understand. My html looks like this:
<script src="https://www.gstatic.com/firebasejs/8.2.6/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.2.6/firebase-firestore.js"></script>
<script type="module">
// Import the functions you need from the SDKs you need
import { initializeApp, } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-app.js";
import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-analytics.js";
import { getFirestore, collection, getDocs, addDoc } from 'https://www.gstatic.com/firebasejs/9.0.2/firebase-firestore.js';
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
const firebaseConfig = { ... } //firebase config
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
const db = getFirestore(app);
const querySnapshot = await getDocs(collection(db, "location")); *** //await is running without async! ***
console.log(querySnapshot)
querySnapshot.forEach((doc, index) => {
// do something with doc
*** // index always returns undefined! ***
}
Problem 1: Async running without await.
Problem 2: Index is undefined after reading and iterating data from firebase.
Please help as I studied js for more than a year and I feel like a complete newbie now.
Thank You Bergi (Profile):
It is indeed a top level await (a feature in moduleJS).
Read more about it here: https://v8.dev/features/top-level-await
Thanks! Dharamraj (Profile) => querySnapshot.docs.forEach() index works perfectly fine now.

React-Native: save user preferences

Native developers,
I really searched a lot but couldn't find anything that fits my needs.
I am new to react native and have a question.
I wonder how I can save user preferences of my app.
For example, I am displaying a dismissible badge on my screen -> user dismisses it -> how do I save this decision so the badge won't appear on every start again?
I thought about writing a .json file where all preferences are defined and read it on every start.
Is this a common way to realize it or is there any other solution.
Thank you very much
Updated Answer at February 2022
React native, officially deprecated the usage of its built-in AsyncStorage. The latest solution is to install the community package of it.
# Install via NPM
npm install --save #react-native-async-storage/async-storage
# ...or install via YARN
yarn add #react-native-async-storage/async-storage
# ...or install via EXPO
expo install #react-native-async-storage/async-storage
And the implementation is like this
import AsyncStorage from '#react-native-async-storage/async-storage';
const storeKey = '#storage_Key'
const storeData = async (value) => {
try {
await AsyncStorage.setItem(storeKey, value)
} catch (e) {
// saving error
}
}
const getData = async () => {
try {
const value = await AsyncStorage.getItem(storeKey)
if(value !== null) {
// value previously stored
}
} catch(e) {
// error reading value
}
}
deprecated doc: https://reactnative.dev/docs/asyncstorage
async storage doc: https://react-native-async-storage.github.io/async-storage/docs/install/
Consider another options: https://reactnative.directory/?search=storage
Old Answer
There are so many options out there, but the most common you can use is the React Native built-in AsyncStorage.
Sample Code
import { AsyncStorage } from "react-native";
const storeKey = 'myPreference';
storeData = async () => {
try {
await AsyncStorage.setItem(storeKey, 'I like to save it.');
} catch (error) {
// Error saving data
}
}
retrieveData = async () => {
try {
const value = await AsyncStorage.getItem(storeKey);
if (value !== null) {
// We have data!!
console.log(value);
}
} catch (error) {
// Error retrieving data
}
}
read more at https://facebook.github.io/react-native/docs/asyncstorage.html
Or you could reconsider 3rd party library like:
https://github.com/kevinresol/react-native-default-preference
https://github.com/mCodex/react-native-sensitive-info

Categories

Resources