Error reading data in Firestore with Nuxt Js using Fetch Hook - firebase

I was trying to do pagination with firebase and nuxt js . When trying to read from firestore using the fetch hook I get an error (Maximum call stack size exceeded ). It is worth noting that when doing this same process with the hook mounted works perfectly. I need to use the fetch hook for ssr. I think the error comes from assigning the value to the variable lastDoc which I need to save the cursor that I will later use in the pagination.
Here is the code
async fetch() {
let queryShows = query(
collection(db, "shows"),
orderBy("ano", "desc"),
orderBy("nombre", "asc"),
limit(3)
);
const querySnapshotShows = await getDocs(queryShows);
this.lastDoc = querySnapshotShows.docs[querySnapshotShows.docs.length - 1]; //Don't know why this cause an error
querySnapshotShows.forEach((doc) => {
this.shows.push({ id: doc.id, ...doc.data() });
});}
Here is the error
Error Image

Related

NuxtJS store returning local storage values as undefined

I have a nuxt application. One of the components in it's mounted lifecycle hook is requesting a value from the state store, this value is retrieved from local storage. The values exist in local storage however the store returns it as undefined. If I render the values in the ui with {{value}}
they show. So it appears that in the moment that the code runs, the value is undefined.
index.js (store):
export const state = () => ({
token: process.browser ? localStorage.getItem("token") : undefined,
user_id: process.browser ? localStorage.getItem("user_id") : undefined,
...
Component.vue
mounted hook:
I'm using UserSerivce.getFromStorage to get the value directly from localStorage as otherwise this code block won't run. It's a temporary thing to illustrate the problem.
async mounted() {
// check again with new code.
if (UserService.getFromStorage("token")) {
console.log("user service found a token but what about store?")
console.log(this.$store.state.token, this.$store.state.user_id);
const values = await ["token", "user_id"].map(key => {return UserService.getFromStorage(key)});
console.log({values});
SocketService.trackSession(this, socket, "connect")
}
}
BeforeMount hook:
isLoggedIn just checks that the "token" property is set in the store state.
return !!this.$store.state.token
beforeMount () {
if (this.isLoggedIn) {
// This runs sometimes??? 80% of the time.
console.log("IS THIS CLAUSE RUNNING?");
}
}
video explanation: https://www.loom.com/share/541ed2f77d3f46eeb5c2436f761442f4
OP's app is quite big from what it looks, so finding the exact reason is kinda difficult.
Meanwhile, setting ssr: false fixed the errors.
It raised more, but they should probably be asked into another question nonetheless.

How to send a file with RTK Query from Redux Toolkit?

I am trying to use RTK Query mutations to upload a file to the API. Here is my mutation code:
addBanner: builder.mutation({
query(body) {
return {
url: `/api/banners`,
method: 'POST',
body,
}
},
})
Here is how I generate the data for request.
const [addBanner, { isBannerLoading }] = useAddBannerMutation();
const new_banner = new FormData();
new_banner.append("file", my_file);
new_banner.append("type", my_type);
new_banner.append("title", my_title);
addBanner(new_banner).unwrap().then( () => ...
But I get an error:
A non-serializable value was detected in the state, in the path: `api.mutations.L-Mje7bYDfyNCC4NcxFD3.originalArgs.file`...
I know I can disable non-serializable check entirely through middleware, but I don't think it is an appropriate way of using Redux Toolkit and RTK. Without a file all works fine. Is there any right way of uploading files with RTK?
Edit: This has been fixed with #reduxjs/toolkit 1.6.1 - please update your package
I just opened an issue for this: https://github.com/reduxjs/redux-toolkit/issues/1239 - thanks for bringing it up!
For now, you'll probably have to disable that check (you can do so for a certain path in the state while keeping it for the rest with the ignoredPath option).

Firebase emulator always returns Error: 2 UNKNOWN after trying out the firestore background trigger functions?

** This is that my firestore (emulator) looks like**
I am trying to practice learning about cloud functions with firebase emulator however, I am running into this probably more often than I expected. I hope it is my end's problem.
I am trying to write a function where when the user made the https request to create an order, the background trigger function will return out the total (quantity * price) to the user. The later part is still WIP at the moment; I am currently just trying to understand and learn more about cloud functions.
This is the https request code I have to add the item, price, and quantity to my firestore. It works well and as intended.
exports.addCurrentOrder = functions.https.onRequest(async (req, res) => {
const useruid = req.query.uid;
const itemName = req.query.itemName;
const itemPrice = req.query.itemPrice;
const itemQuantity = req.query.itemQuantity;
console.log('This is in useruid: ', useruid);
const data = { [useruid] : {
'Item Name': itemName,
'Item Price': itemPrice,
'Item Quantity': itemQuantity,
}};
const writeResult = await admin.firestore().collection('Current Orders').add(data);
res.json({result: data});
});
This is the part that's giving me all sorts of errors:
exports.getTotal = functions.firestore.document('Current Orders/{documentId}').onCreate((snap, context) => {
const data = snap.data();
for(const i in data){
console.log('This is in i: ', i);
}
return snap.ref.set({'testing': 'testing'}, {merge: true});
});
Whenever I have this, the console will always give me:
functions: Error: 2 UNKNOWN:
at Object.callErrorFromStatus (/Users/user/firecast/functions/node_modules/#grpc/grpc-js/build/src/call.js:30:26)
at Object.onReceiveStatus (/Users/user/firecast/functions/node_modules/#grpc/grpc-js/build/src/client.js:175:52)
at Object.onReceiveStatus (/Users/user/firecast/functions/node_modules/#grpc/grpc-js/build/src/client-interceptors.js:341:141)
at Object.onReceiveStatus (/Users/user/firecast/functions/node_modules/#grpc/grpc-js/build/src/client-interceptors.js:304:181)
at Http2CallStream.outputStatus (/Users/user/firecast/functions/node_modules/#grpc/grpc-js/build/src/call-stream.js:116:74)
at Http2CallStream.maybeOutputStatus (/Users/user/firecast/functions/node_modules/#grpc/grpc-js/build/src/call-stream.js:155:22)
at Http2CallStream.endCall (/Users/user/firecast/functions/node_modules/#grpc/grpc-js/build/src/call-stream.js:141:18)
at Http2CallStream.handleTrailers (/Users/user/firecast/functions/node_modules/#grpc/grpc-js/build/src/call-stream.js:273:14)
at ClientHttp2Stream.<anonymous> (/Users/user/firecast/functions/node_modules/#grpc/grpc-js/build/src/call-stream.js:322:26)
at ClientHttp2Stream.emit (events.js:210:5)
Caused by: Error
at WriteBatch.commit (/Users/user/firecast/functions/node_modules/#google-cloud/firestore/build/src/write-batch.js:415:23)
at DocumentReference.create (/Users/user/firecast/functions/node_modules/#google-cloud/firestore/build/src/reference.js:283:14)
at CollectionReference.add (/Users/user/firecast/functions/node_modules/#google-cloud/firestore/build/src/reference.js:2011:28)
**at /Users/user/firecast/functions/index.js:43:76**
at /usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:593:20
at /usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:568:19
at Generator.next (<anonymous>)
at /usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:8:71
at new Promise (<anonymous>)
at __awaiter (/usr/local/lib/node_modules/firebase-tools/lib/emulator/functionsEmulatorRuntime.js:4:12)
⚠ Your function was killed because it raised an unhandled error.
Even if I comment out the function that I think is giving me the error, I will still run into this problem (and when I run the sample function found on the official cloud function guide too!)
I know there is definitely something that I am doing horribly wrong on the background trigger (and would love to have someone be kind enough to show me how to write such function/get me startted)
What am I doing wrong here? Or is this some sort of the emulator bug?
I think I found it. Although I think there is better solution possible.
On completely new system+firebase I have used this firebase emulators tutorial to create first onCreate trigger called makeUppercase and it worked. Than I added your getTotal and it was not working and as well it spoiled the makeUppercase trigger as well!
I started to test some changes. Tried many times and, finally, I have removed "space" character from collection name like this:
exports.getTotal = functions.firestore.document('CurrentOrders/{documentId}')...etc.
Both triggers started working as well (used fresh VM with Windows+node12). It's possible that it will be working on real Firestore instance. So it seems the "space" in collection name is generating some errors in whole index.js.

firebase onSnapshot gets update before create is complete

I have a "post" that listens to changes on its comments in react like so:
// React hook state
const [comments, setComments] = useState([])
// My listener in useEffect
db.collection(`users/${userId}/posts/${postId}/comments`)
.onSnapshot((querySnapshot) => {
let newComments = []
querySnapshot.forEach(function (doc) {
newComments.push({
id: doc.id,
...doc.data()
})
})
setComments(newComments)
})
When the user creates a new comments, I set a loading state and disable the comment section
// React hook
const [isLoading, setLoading] = useState(false)
// Add comment
const addComment = () => {
const comment = {text:"hello"}
setSaving(true)
db.collection(`users/${postUid}/posts/${postId}/comments`).doc()
.set(comment)
.then(()=>{
setSaving(false)
})
}
My problem is (a good problem to have), the subscription onSnapshot gets the new comment before my addComment callback is completed, creating some visual issues:
- Makes the app look buggy when the comment input is still loading but the comment already there
- If there is an error (ex: database permission issue), the comment shows up in the list and then disappears...
Any idea what I can change to not have the onSnapshot update before the create is done?
As explained here in the doc:
Local writes in your app will invoke snapshot listeners immediately.
This is because of an important feature called "latency compensation."
When you perform a write, your listeners will be notified with the new
data before the data is sent to the backend.
Retrieved documents have a metadata.hasPendingWrites property that
indicates whether the document has local changes that haven't been
written to the backend yet.
See also the following remark in the "Listen to multiple documents in a collection" section:
As explained above under Events for local changes, you will receive
events immediately for your local writes. Your listener can use the
metadata.hasPendingWrites field on each document to determine whether
the document has local changes that have not yet been written to the
backend.
So you can use this property to display the change only if it has been written to the back-end, something along the following lines (untested):
db.collection(`users/${userId}/posts/${postId}/comments`)
.onSnapshot((querySnapshot) => {
let newComments = []
querySnapshot.forEach(function (doc) {
if (!doc.metadata.hasPendingWrites) {
newComments.push({
id: doc.id,
...doc.data()
})
}
})
setComments(newComments)
})

Firestore in Cloud Functions - Create a missing index through an error message

When using Firestore in Cloud Functions, how to use the Create a missing index through an error message feature?
Basically, after I use a new Firestore query in my Cloud Function, where should I expect to find the "error message [that] includes a direct link to create the missing index"?
Update: add sample code based on a comment suggestion
Assume the query below wasn't used before. After I deploy the function to Cloud Functions and use it, where can I find the automatically-created link for creating the missing index?
import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
export const posts = functions.https.onCall(async (
data: { uid: string },
context
) => {
// ...
const querySnapshot = await postsRef
.where('uid', '==', data.uid)
.orderBy('timestamp', 'desc')
.get();
// ...
});
When you perform the query, the resulting promise will become rejected. Your code will need to catch that error from the rejected promise, then log the error object. The url will be in the log message. (I'm assuming you're using node here, but the same error handling will apply to any language using its conventions for capturing and logging errors.)

Resources