Firebase returning undefinfed - firebase

I keep getting a response undefined with the return function. After a second the console.log displays the information. My guess is that the data is still being gathered and that the function is already returning. I thought it would be solved with a promise but it has not. What am I missing? why is my function returning without any data?
TakenSpaces = 0
let startDate = new Date(time)
startDate.setHours(0)
startDate.setMinutes(0)
let endDate = new Date(startDate)
endDate.setHours(24)
data = []
const reservations = db.collection('organisation').doc('Amigos').collection('reservations')
.where('start', '>=', startDate)
.where('start', '<=', endDate).get()
console.log('promse made')
reservations.then((docs) => {
// console.log(docs.data())
// return docs.data()
// const promises = []
docs.forEach((doc) => {
data.push(doc.id)
})
// console.log(data)
// console.log('DONE TESTING')
return data
// return Promise.all(promises)
})
.then((test) => { console.log(test); return test })
// for (const reservation of reservations) {
// console.log(reservation)
// }
// .then((docs) => {
// // for (const doc of docs) {
// // console.log(doc.id)
// // }
// docs.forEach((doc) => {
// if (doc.data().people){
// const people = doc.data().people
// TakenSpaces = TakenSpaces + people
// }
// // console.log(doc.data().people)
// });
// return TakenSpaces
// })
// return TakenSpaces
}
const t = getTakenCapacity(time)
console.log(t)

It works know. But If anyone knows if the function can only return when everything is finished and not have to return a promise function.
function getTakenCapacity (time) {
TakenSpaces = 0
let startDate = new Date(time)
startDate.setHours(0)
startDate.setMinutes(0)
let endDate = new Date(startDate)
endDate.setHours(24)
data = []
const reservations = db.collection('organisation').doc('Amigos').collection('reservations')
.where('start', '>=', startDate)
.where('start', '<=', endDate).get()
return reservations.then((docs) => {
// console.log(docs.data())
// return docs.data()
// const promises = []
var dd = new Array
docs.forEach((doc) => {
data.push([[time], doc.data().people])
})
// console.log(data)
// console.log('DONE TESTING')
return data
// return Promise.all(promises)
})
getTakenCapacity(time).then(function(result) {
console.log(result) // "Some User token"
})

Related

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: "

Firebase Query Collection along with its Subcollection - React Native

How to query collection of firebase so that it also includes its subcollection? So I have collection posts with documents and every document has field subcollection likes. After getting collection posts I have objects and inside them values of fields, but inside each object (post) I want to have besides those values an object aka subcollection likes.
Queries in Firestore are by definition shallow. There is no way to get results from both a parent collection and its subcollections in a single query.
When I want all data from a parent document and a subcollection in the same operation, and it's not too much, I typically (also) include it in the parent document.
Ive done in it this function but i dont feel like making it look pretty theres tons of code that isnt needed here anyways here is solution maybe it helps someone:
getPosts = async () => {
this.setState({ isLoading: true });
const snapshot = await firebase
.firestore()
.collectionGroup("posts")
.orderBy("id", "desc")
.limit(7)
.get();
let array = [];
const snap = await firebase
.firestore()
.collection("posts")
.get();
for (let i = 0; i < snap.docs.length; i++) {
array.push(snap.docs[i].data().id);
//console.log(array);
//newpost[i].userHandle = [result]; //your new object here
}
if (!snapshot.empty) {
let newpost = [];
this.setState({ lastDoc: snapshot.docs[snapshot.docs.length - 1] });
// snapshot.forEach((doc) => {
// const PostItem = doc.data();
// PostItem.id = doc.id;
// newpost.push(PostItem);
// });
let newpost2 = [];
let result = [];
let finish = [];
let groupByKey = [];
let bruh = [];
let uf = [];
const listOfPosts = await firebase.firestore().collection("posts").get()
.then((val) => val.docs);
for (var i=0; i<listOfPosts.length; i++)
{
const snapshot = await firebase.firestore().collection("posts").doc(
listOfPosts[i].id.toString())
.collection("hugs").get();
snapshot.forEach(doc => {
newpost2.push(doc.data());
result = newpost2.map(a => a.userHandle)
//console.log(newpost2)
newpost2.map(obj=> ({ ...obj, result}))
//console.log(newpost2)
groupByKey.push((list, key, {omitKey=false}) => list.reduce((hash, {[key]:value, ...rest}) => ({...hash, [value]:( hash[value] || [] ).concat(omitKey ? {...rest} : {[key]:value, ...rest})} ), {}))
groupByKey.push((newpost2, 'id', {omitKey:false}))
uf = [];
newpost2.forEach((obj)=> {
if(typeof uf[obj.id] === 'undefined') {
uf[obj.id] = {id: obj.id, userHandle: [obj.userHandle]}
}
else {
uf[obj.id].userHandle.push(obj.userHandle);
}
});
uf = uf.filter(item => !(item == "undefined"));
//console.log(groupByKey)
//this.setState({ post: [...newpost,] });
});
//finish = a1.map(t1 => ({...t1, ...a2.find(t2 => t2.id === t1.id)}))
//console.log(newpost2)
}
for (let i = 0; i < snapshot.docs.length; i++) {
newpost.push(snapshot.docs[i].data());
//newpost[i].username = result;
//newpost[i].userHandle = [result]; //your new object here
}
//var element = {}, cart = [];
//newpost.id = id;
//element.quantity = quantity;
//newpost2.push(newpost);
// Array of Objects in form {element: {id: 10, quantity: 10} }
finish = newpost.map(t1 => ({...t1, ...uf.find(t2 => t2.id === t1.id)}))
//if(Object.keys(groupByKey) === t1.id){console.log("nigba")}
//var result2 = newpost.map(function(e) {
//var find = groupByKey.find(a => a.email == e.email);
//return console.log(Object.assign({}, e, find))
//})
console.log(finish)
this.setState({ post: [...newpost,] });
//console.log(this.state.post)
} else {
this.setState({ lastDoc: null });
}
this.setState({ isLoading: false });
//setTimeout(
//console.log(this.state.post)
//, 50000);
};

How to use chained promises inside firebase functions?

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

How to avoid promise nesting

I have a feeling I'm doing an overkill nesting in the following simple function, which simply reads a value from one location and writes it to another location.
Is there a way to simplify it somehow?
exports.myFunc = functions.database.ref('...').onCreate(event => {
const list_id = event.params.list_id;
return new Promise(function(resolve, reject){
event.data.adminRef.root.child('lists').child(list_id).child('owner').once('value').then(function(snap){
const owner_id = snap.val();
if (owner_id != null) {
event.data.adminRef.root.child('users').child(owner_id).child('whatever').child('whatever2').set(true)
.then(function() {
resolve();
},
function(err) {
reject();
}
)
} else {
reject();
}
});
});
})
You don't need a new promise if you have existing promises to work with. You can return promises from then to continue chaining.
exports.myFunc = functions.database.ref('...').onCreate(event => {
const list_id = event.params.list_id;
return event.data.adminRef.root.child('...').once('value')
.then(function(snap){
const owner_id = snap.val();
if (owner_id != null) {
return event.data.adminRef.root.child('...').set(true)
} else {
return Promise.reject('error message')
}
});
})

Error: must return a plain object, instead received undefined

My console output is producing the correct objects then crashing at the end of the array map and I can't figure out what's undefined. Here is my reducer, action, and list implement.
reducer:
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case LOCATION_FETCH_SUCCESS:
return action.payload;
case POSTS_FETCH_FAIL:
return state;
default:
return state;
}
};
action creator:
export const locationFetch = () => {
const geoFire = new GeoFire(firebase.database().ref('/geoLocations'));
var keys = [];
var snaps = [];
return (dispatch) => {
navigator.geolocation.getCurrentPosition(
(position) => {
const currentLocation = [position.coords.latitude, position.coords.longitude];
const radius = 0.5;
const geoQuery = geoFire.query({ center: currentLocation, radius });
var onKeyEntered = geoQuery.on("key_entered", (key) => {
keys.push(key);
console.log(key);
});
var onKeyReady = geoQuery.on('ready', () => {
keys.map((key) => {
firebase.database().ref('/posts').child(key).
once('value').then((snapshot) => {
snaps.push(snapshot.val());
// console.log(snaps);
dispatch({ type: LOCATION_FETCH_SUCCESS, payload: snaps });
});//.catch(() => postsFetchFail(dispatch));
});
});
});
};
};
mapstatetoprops:
const mapStateToProps = state => {
var objectArray = _.values(state.posts)
objectArray = _.flatten(objectArray);
//console.log(objectArray);
objectArray.map((post) => {
const { dishname,
restaurant,
category,
likesCount
} = post;
console.log({ dishname , restaurant });
return { dishname, restaurant };
});
};
export default connect(mapStateToProps, {locationFetch})(DshdList);
The last output to the console and the error message I am getting are as follows:
10:43:33 PM
Object {
"dishname": "shrimp bun",
"restaurant": "momofuku ",
}
10:43:38 PM
â–¼mapStateToProps() in Connect(DshdList) must return a plain object. Instead received undefined
I do not get where this is going wrong.
You must return object from mapStateToProps function, which you are missing. Place a return statement like below
return objectArray.map(...);
Hope this will help.

Resources