Cannot fix Promise in react native Promise { "_U": 0, "_V": 0, "_W": null, "_X": null, } - firebase

Why did I add Promise to the function it still gives an error ??
I cannot call this function again with the parameter I give ??
Get User by Uid in Fire.js file( I custom this file )
getUserbyUid = async ({ Uid }) => {
return new Promise((res, rej) => {
firebase.firestore()
.collection('user')
.doc(Uid)
.get()
.then(documentSnapshot => {
res(documentSnapshot.data().name);
})
.catch(error => { rej(error) });
})
}
in Feed.js i call it
async componentDidMount() {
await firebase.firestore().collection("Post").get()
.then(querySnapshot => {
querySnapshot.forEach(documentSnapshot => {
this.setState({ dataPost: this.state.dataPost.concat({ ...documentSnapshot.data(),
key: documentSnapshot.id, }) })
console.log(Fire.shared.getUserbyUid(documentSnapshot.data().uid)); <= error this if i console.log(documentSnapshot.data().uid)) it will return a Uid
but If i call in above it will return Promise { "_U": 0,"_V": 0, "_W": null,"_X": null,}
});
});
}

Related

How to correctly return the result from Cloud Function?

I am trying to implement verification using Cloud Function and Twilio. Twilio works correctly and SMS with the code is sent, but in the Flutter application I get the error [firebase_functions / deadline-exceeded] DEADLINE_EXCEEDE. What am I doing wrong?
Cloud Function:
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const client = require('twilio')(accountSid, authToken);
exports.sendSms = (req, res) => {
console.log('start sendSms');
var func = client.verify.services('xxxxx')
.verifications
.create({to: req.body.data.phone, channel: 'sms'})
.then(verification => {return verification})
.then(result => {
if (result.status === 'pending')
return {status: 'success', result: "pending"};
else
return {status: 'error', error_code: -1, error_msg: result.status};
})
.catch(e => {
return {status: 'error', error_code: e.code, error_msg: e.message};
});
return Promise.all([func]).then(result => {
console.log(result); // console output [ { status: 'success', result: 'pending' } ]
return result[0];
});
};
Flutter:
HttpsCallable callable = FirebaseFunctions.instanceFor(region: 'europe-west3').httpsCallable(
'send-sms',
options: HttpsCallableOptions(timeout: const Duration(seconds: 10))
);
dynamic results = await callable.call(<String, dynamic>{'phone': phoneNumber});
The create method returns promise too so you must add the return keyword there as well.
Instead of:
var func = client.verify.services('xxxxx')
Try this:
exports.sendSms = functions.https.onCall((data, context) => {
//^^^^^^^^^^^^^^^^^^^^^^
console.log('start sendSms');
return client.verify.services('xxxxx')
.verifications
.create({to: data.phone, channel: 'sms'})
.then(verification => {return verification})
.then(result => {
if (result.status === 'pending')
return {status: 'success', result: "pending"};
else
return {status: 'error', error_code: -1, error_msg: result.status};
})
.catch(e => {
return {status: 'error', error_code: e.code, error_msg: e.message};
});
});
That being said you don't need this part:
return Promise.all([func]).then(result => {
console.log(result); // console output [ { status: 'success', result: 'pending' } ]
return result[0];
});

Firebase get request querying multiple tables

I'm trying to send get request to get the information of a row and that of its comments and options (rows, comments, options are all different tables). Currently, the request returns the row and comment info, but an empty array for the options, like so:
{
"categoryId": "Category1",
"dataType": "Text",
"approveCount": 0,
"createdAt": "10:00",
"body": "testneww",
"disapproveCount": 0,
"index": 1,
"visit": "Both",
"rowId": "ID",
"comments": [
{
"rowId": "ID",
"createdAt": "2021-02-28T21:32:52.841Z",
"body": "test comment"
}
],
"options": []
}
code:
exports.getOneRow = (req, res) => {
let rowData = {};
db.doc(`/rows/${req.params.rowId}`)
.get()
.then((doc) => {
if (!doc.exists) {
return res.status(404).json({ error: 'Row not found' });
}
rowData = doc.data();
rowData.rowId = doc.id;
return db
.collection('comments')
.orderBy('createdAt', 'desc')
.where('rowId', '==', req.params.rowId)
.get();
})
.then((data) => {
rowData.comments = [];
data.forEach((doc) => {
rowData.comments.push(doc.data());
})
return db
.collection('options')
.orderBy('index', 'asc')
.where('rowId', '==', req.params.rowId)
.get();
})
.then((newData)=>{
rowData.options = [];
newData.forEach((newDoc) => {
rowData.options.push(newDoc.data());
})
return res.json(rowData);
})
.catch((err) => {
console.error(err);
res.status(500).json({ error: err.code });
});
};
I presume I'm making a silly mistake somwhere, or is it not possible to do a request like this? Any help appreciated!
The following code worked, I cant see any differences besides adding the parameters individually in 'rowData.options.push' near the end, however ive been staring at the same code for quite a while so please do let me know if im missing something else.
exports.getOneRow = (req, res) => {
let rowData = {};
db.doc(`/rows/${req.params.rowId}`)
.get()
.then((doc) => {
if (doc.exists) {
rowData = doc.data();
rowData.rowId = doc.id
return db
.collection("comments")
.where("rowId", "==", req.params.rowId)
.get();
} else{
return res.status(500).json({ error: err.code });
}
})
.then((data) => {
rowData.comments = [];
data.forEach((doc) => {
rowData.comments.push(doc.data());
});
return db
.collection("options")
.where("rowId", "==", req.params.rowId)
.orderBy("index", "asc")
.get();
})
.then((data) => {
rowData.options = [];
data.forEach((doc) => {
rowData.options.push({
index: doc.data().index,
body: doc.data().body,
rowId: doc.data().rowId,
});
});
return res.json(rowData);
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
};

because my return is [{"singles": [[Object], [Object]]}]

I am using a useEffect to get information from a collection and a sub-collection, however, the data return from my sub-collection is being [{"singles": [[Object], [Object]]}]
useEffect(() => {
fireStore
.collection('users')
// .where('category','==','band')
// .where('status','==','approved')
.where('email','==','marcelomenoli12#gmail.com')
.get()
.then( async (musics) => {
const allSingles = musics.docs.map(async (single) => {
const items = await single.ref.collection('musics').get();
return {
// cover: single.data().cover,
// name: single.data().bandArtistName,
singles: items.docs.map((item) => ({
id: item.id,
...item.data(),
}))
}
});
const filteredSingles = await Promise.all(allSingles);
setDATA(filteredSingles);
});
}, []);
console.log(DATA);
You should use more than one then clauses, so every async operation return values. Otherwise inner await responses are not come on time.
I tried to update your code. I hope that helps.
useEffect(() => {
fireStore
.collection('users')
.where('email','==','marcelomenoli12#gmail.com')
.get()
.then( async (musics) => {
const allSingles = musics.docs.map(async (single) => {
return await single.ref.collection('musics').get();
})
.then((items)=>{
// cover: single.data().cover,
// name: single.data().bandArtistName,
singles: items.docs.map((item) => ({
id: item.id,
...item.data(),
}))
})
}, []);
console.log(DATA);

Unsubscribe Firestore listener on logout

The straightforward way to do this is explained here
However i am having a hard time trying to trigger the unsubscribe within a onAuthStateChanged which is in a different vuex module
store/user.js
...
onAuthStateChanged({ commit, dispatch }, { authUser }) {
if (!authUser) {
commit('RESET_STORE')
this.$router.push('/')
return
}
commit('SET_AUTH_USER', { authUser })
dispatch('database/getUserItems', null, { root: true })
this.$router.push('/home')
}
...
store/database.js
...
getUserItems({ state, commit }, payload) {
const unsubscribe = this.$fireStore
.collection('useritems')
.where('owner', '==', this.state.user.authUser.uid)
.onSnapshot(
(querySnapshot) => {
querySnapshot.forEach(function(doc) {
// STUFF
},
(error) => {
console.log(error)
}
)
},
...
How do i reference unsubscribe() from the user.js module when the user logs out (authUser undefined)?
I think you can just save it in you Vuex state tree and call it from there.
state: {
//....
listenerUnsubscribe: null,
//....
},
mutations: {
//....
SET_LISTENER_UNSUBSCRIBE(state, val) {
state.listenerUnsubscribe = val;
},
RESET_STORE(state) {
state.listenerUnsubscribe()
}
//....
},
actions: {
//....
getUserItems({ state, commit }, payload) {
const unsubscribe = this.$fireStore
.collection('useritems')
.where('owner', '==', this.state.user.authUser.uid)
.onSnapshot((querySnapshot) => {
querySnapshot.forEach(function(doc) {
// STUFF
},
(error) => {
console.log(error)
}
);
commit('SET_LISTENER_UNSUBSCRIBE', unsubscribe);
},

TypeError: Cannot set property 'words' of undefined

I have this action in my vuex store:
loadExercises ({commit}) {
commit('setLoading', true)
const db = firebase.firestore()
db.collection('exercises').get()
.then(querySnapshot => {
const exercises = []
querySnapshot.forEach((doc) => {
exercises.push({
title: doc.data().title,
language: doc.data().language,
translated: doc.data().translated,
lastOpen: doc.data().lastOpen,
dueDate: doc.data().dueDate,
uid: doc.data().uid,
userId: doc.data().userId,
words: [{ word: '', uid: '', translation: '' }]
})
db.collection('exercises').doc(doc.data().uid).collection('words').get()
.then(words => {
const wordsArray = []
words.forEach(word => {
wordsArray.push(word.data())
})
let exercise = this.getters.loadedExercise(doc.data().uid)
exercise.words = wordsArray
})
.catch(error => {
commit('setLoading', false)
console.log(error)
})
})
commit('setLoading', false)
commit('setLoadedExercises', exercises)
})
.catch(error => {
commit('setLoading', false)
console.log(error)
})
}
It is supposed to fetch exercises from a firebase cloudstore db. It works on some routes but not all.
When using these two getters it works:
loadedExercises (state) {
return state.loadedExercises
},
loadedExercise (state) {
return (exerciseId) => {
return state.loadedExercises.find(exercise => {
return exercise.uid === exerciseId
})
}
}
But when I use these getters:
upcomingExercises (state, getters) {
return getters.loadedExercises.filter(exercise => {
return exercise.dueDate > 0
})
},
latestExercises (state, getters) {
return getters.loadedExercises.splice(0, 5)
},
it does not work I just get "TypeError: Cannot set property 'words' of undefined". What is it that I do wrong?
It looks to me like you aren't returning the values back to the function.
Try replacing
db.collection('exercises').get()
with
return db.collection('exercises').get()
and
db.collection('exercises').doc(doc.data().uid).collection('words').get()
with
return db.collection('exercises').doc(doc.data().uid).collection('words').get()

Resources