How to use chained promises inside firebase functions? - firebase

I created a firebase function that updates the like count of an comment or post when a new like document is created.
But it throws an 404 error.
exports.updateLikeCount = functions.firestore
.document('likes')
.onCreate((snap, context) => {
const likeObj = snap.data();
if(likeObj.isComment) {
const { _comment } = likeObj;
const commentRef = fstore.collection('comments').doc(_comment);
return commentRef.get()
.then(doc => {
let { likes } = doc.data();
++likes;
return commentRef.update({
likes
});
});
}else {
const { _post } = likeObj;
const postRef = fstore.collection('posts').doc(_post);
return postRef.get()
.then(doc => {
let { likes } = doc.data();
++likes;
return postRef.update({
likes
});
});
}
});
NOTE:
_post and _comment are post ID and comment ID respectively

Related

How to call RTK mutations after first finishes

I am using REDUX-TOOLKIT-QUERY, Now I have a situation, I have to call one mutation. once that mutation returns a response, and I have to use that response in the other three mutations as a request parameter. How can we implement this in a proper way?
const [getSettings, { isLoading, data: Settings }] =useSettingsMutation();
const [getMenu] =useMenuMutation();
const [getServices] = useServicesMutation();
useEffect(() => {
const obj = {
Name: "someNme",
};
if (obj) getSettings(obj);
if (Settings?._id ) {
const id = settings._id;
getServices(id);
getMenu(id);
getServices(id);
}
}, []);
useMutation will return a promise, you can directly await this promise to get the return result:
const [getSettings, { isLoading, data: Settings }] = useSettingsMutation()
const [getMenu] = useMenuMutation()
const [getServices] = useServicesMutation()
useEffect(() => {
;(async () => {
try {
const obj = {
Name: 'someNme',
}
const data = await getSettings(obj).unwrap()
if (data._id !== undefined) {
const id = data._id
getServices(id)
getMenu(id)
getServices(id)
// ...
}
} catch (err) {
// ...
}
})()
}, [])

Update Component after post new item to the Database

I am playing around with Sveltekit and I am struggling a bit..
So my problem is, when I add something to the DB it works, but the new Item does not show in the list until i Refresh the page. My Code looks like:
index.js
import { connectToDatabase } from '$lib/db';
export const post = async ({ request}) => {
const body = await request.json()
console.log(body)
const dbConnection = await connectToDatabase();
const db = dbConnection.db;
const einkaufszettel = db.collection('Einkaufszettel')
await einkaufszettel.insertOne({
name: body.newArticle
});
const einkaufsliste = await einkaufszettel.find().toArray();
return {
status: 200,
body: {
einkaufsliste
}
};
}
export const get = async () => {
const dbConnection = await connectToDatabase();
const db = dbConnection.db;
const einkaufszettel = db.collection('Einkaufszettel')
const einkaufsliste = await einkaufszettel.find().toArray();
console.log(einkaufsliste)
return {
status: 200,
body: {
einkaufsliste,
}
};
}
and the Script of index.svelte
<script>
import Title from '$lib/title.svelte'
export let einkaufsliste = []
let newArticle = ''
const addArticle = async () => {
const res = await fetch('/', {
method: 'POST',
body: JSON.stringify({
newArticle
}),
headers: {
'Content-Type': 'application/json'
}
})
fetchArticles()
}
async function fetchArticles() {
const res = await fetch('/')
console.log(res.body)
}
</script>
In the Network Preview Tab the new Item is already added to the List.
As you can read here, you need to reassign the einkaufsliste after fetching the list of elements from the API.
You can do this in your fetchArticles method, like this:
async function fetchArticles() {
einkaufsliste = await fetch('/')
}

Solution to prefetch in a component on nextjs

I'm looking for a solution/module where I don't need to inject inital/fallback data for swr/react-query things from getServerSideProps. Like...
from
// fetcher.ts
export default fetcher = async (url: string) => {
return await fetch(url)
.then(res => res.json())
}
// getUserData.ts
export default function getUserData() {
return fetcher('/api')
}
// index.tsx
const Page = (props: {
// I know this typing doesn't work, only to deliver my intention
userData: Awaited<ReturnType<typeof getServerSideProps>>['props']
}) => {
const { data } = useSWR('/api', fetcher, {
fallbackData: props.userData,
})
// ...SSR with data...
}
export const getServerSideProps = async (ctx: ...) => {
const userData = await getUserData()
return {
props: {
userData,
},
}
}
to
// useUserData.ts
const fetcher = async (url: string) => {
return await fetch(url)
.then(res => res.json())
};
const url = '/api';
function useUserData() {
let fallbackData: Awaited<ReturnType<typeof fetcher>>;
if (typeof window === 'undefined') {
fallbackData = await fetcher(url);
}
const data = useSWR(
url,
fetcher,
{
fallbackData: fallbackData!,
}
);
return data;
}
// index.tsx
const Page = () => {
const data = useUserData()
// ...SSR with data...
}
My goal is making things related to userData modularized into a component.

How to get multiple references in a firestore snapshot

I have a firestore collection containing post documents, each document contains a reference to an author (user) and a case document.
How do I get the user and the case in the same onSnapshot?
Here's what I'd like to do with await, but that doesn't seem to be an option with react-native-firebase.
export const firebasePostLooper = (snapshot) => {
let data = [];
snapshot.forEach(async (doc) => {
let newItem = {id: doc.id, ...doc.data()};
if (newItem.author) {
let authorData = await getDoc(newItem.author); // doesn't work with rnfirebase
if (authorData.exists()) {
newItem.userData = {userID: authorData.id, ...authorData.data()};
}
}
if (newItem.case) {
let caseData = await getDoc(newItem.case);
if (caseData.exists()) {
newItem.userData = {userID: caseData.id, ...caseData.data()};
}
}
data.push(newItem);
});
return data;
};
This doesn't work because getDoc() doesn't exist.
So I'm left with using .then()
export const firebasePostLooper = (snapshot) => {
let data = [];
snapshot.forEach((doc) => {
let newItem = {id: doc.id, ...doc.data()};
if (newItem.author) {
newItem.author
.get()
.then((res) => {
newItem.authorData = res.data();
if (newItem.case) {
newItem.case
.get()
.then((caseRes) => {
newItem.caseData = caseRes.data();
data.push(newItem);
})
.catch((err) => console.error(err));
}
})
.catch((err) => console.error(err));
} else {
data.push(newItem);
}
});
return data;
};
This second method doesn't seem to be working, data is empty at the return statement but data.push(newItem) contains the correct document with the 2 referenced documents.
You're returning data before it gets filled inside the promise. You should handle the returning of the data inside a .then() in order to return it after the promise has resolved and not before.
Take a look at this example where if we handle the emptyData object outside the promise chain, we just return the initial value before it has been filled.
let promise = new Promise((resolve, reject)=>{
setTimeout(resolve, 1000, 'foo');
})
let emptyData= [];
let notEmptyData = [];
promise
.then(res=>{
emptyData.push(res);
notEmptyData.push(res);
console.log("Full data: " + notEmptyData) // "Full data: foo"
});
console.log("Empty data: " + emptyData); // "Empty data: "

React native cannot set multiple arrayitems from Firebase in loop

I am trying to get data from Firebase realtime database in the loop and set array items,
but just the last item can set.
it's looking like synchronize problems I tried a lot of things but couldn't solve it.
import FireBaseConnection from '../classes/firebaseconnection.js';
const getComments = () => {
let cardatafetch=[]
FireBaseConnection.GetData('/PostComments/1234').then((comments) => {
for (i in comments) {
cardatafetch.push(comment[i])
}
for (j in cardatafetch) {
var UserId = cardatafetch[j]["UserID"]
FireBaseConnection.GetData('/Users/'+UserId).then((user) => {
cardatafetch[j].ProfilePicture=user["ProfilePicture"]
})
.catch((error) => {
console.log(error)
});
}
console.log(cardatafetch)
}).catch((error) => {
console.log(error)
});
}
}
Console Output is
Same problem also during get images from storage
for (j in cardatafetch) {
FireBaseConnection.GetImage().then((obj) => {
cardatafetch[j].ProfilePicture=obj
})
.catch((error) => {
console.log(error)
});
}
FireBaseConnection Class
import database from '#react-native-firebase/database';
import storage from '#react-native-firebase/storage';
import { utils } from '#react-native-firebase/app';
class FireBaseConnection
{
static async GetData(refValue) {
let data;
await database()
.ref(refValue)
.once('value')
.then(snapshot => {
data = snapshot.val();
});
return data;
}
static async GetImage(imgValue) {
const reference = storage().ref(imgValue);
let imagePath= await reference.getDownloadURL().then(result =>result);
return imagePath;
}
}
export default FireBaseConnection;
Try below code, what I have done is put your code inside last iteration of the loop so it will be implemented only once when all the items are pushed in the array.
import FireBaseConnection from '../classes/firebaseconnection.js';
const getComments = () => {
return new Promise((resolve, reject) => {
let commentsArr = [];
FireBaseConnection.GetData('/PostComments/1234').then((comments) => {
Object.keys(comments).forEach((key, index) => {
commentsArr.push(comments[key])
if(index == Object.keys(comments).length-1) {
resolve(commentsArr);
}
});
}).catch((error) => {
console.log(error)
});
});
}
const addImagesToComment = () => {
this.getComments().then((comments) => {
var finalArr = [];
comments.forEach((comment, index) => {
var tempComment = comment;
var UserId = comment["UserID"]
FireBaseConnection.GetData('/Users/' + UserId).then((user) => {
tempComment.ProfilePicture = user["ProfilePicture"]
finalArr.push(tempComment);
}).catch((error) => {
console.log(error)
});
if(index == comments.length-1) {
console.log(finalArr)
}
});
});
}
Try calling getComments function.

Resources