Firebase: How to reference a path in Firebase using a variable - javascript

I'm trying to reference a variable in my Firebase Realtime Database, but my console doesn't display the data that I want. The right uid is logged, however, I don't know how to reference the variable called serial.
componentDidMount() {
const uid = this.state.user.uid;
console.log(uid);
const serial = db.ref(uid + "/serial");
console.log(serial);
Here is the console
Here is my database
Thanks in advance!

If I correctly understand your question you want to get the value of the uid/serial node.
By doing const serial = db.ref(uid + "/serial"); you define a Reference. You need to query the data at this Reference, by using the once() or the on() methods.
For example:
const serialRef = db.ref(uid + "/serial");
serialRef.once('value')
.then(function(dataSnapshot) {
console.log(dataSnapshot.val());
});
Note that the once() method is asynchronous and returns a Promise which resolves with a DataSnapshot.

Can you try this:
componentDidMount() {
const uid = this.state.user.uid;
console.log(uid);
const dbItem = db.ref(uid);
console.log(dbItem.serial);
}

Related

Firebase real time database access data array from deleted node

I am deleting a FRTDB node, I want to access deleted data from that node. the functions looks as follow:
exports.events = functions.database.ref('/events/{eventId}').onWrite(async (change, context) => {
const eventId = context.params.eventId
if (!change.after.exists() && change.before.exists()) {
//data removed
return Promise.all([admin.database().ref(`/events/${eventId}/dayofweek`).once('value')]).then(n => {
const pms = []
const days = n[0]
days.forEach(x => {
pms.push(admin.database().ref(`${change.before.val().active ? 'active' : 'inactive'}/${x.key}/${eventId}`).set(null))
})
return Promise.all(pms)
});
else {
return null;
}
})
The probem I am having is that
admin.database().ref(`/events/${eventId}/dayofweek
do not loop the data because it seems data is no longer there so the forEach is not working. How can I get access to this data and get to loop the deleted data?
Of course you won't be able to read data that was just deleted. The function runs after the delete is complete. If you want to get the data that was just deleted, you're supposed to use change.before as described in the documentation:
The Change object has a before property that lets you inspect what was
saved to Realtime Database before the event. The before property
returns a DataSnapshot where all methods (for example, val() and
exists()) refer to the previous value. You can read the new value
again by either using the original DataSnapshot or reading the after
property. This property on any Change is another DataSnapshot
representing the state of the data after the event happened.
The data that was deleted from the database is actually included in the call to your Cloud Function. You can get if from change.before.
exports.events = functions.database.ref('/events/{eventId}').onWrite(async (change, context) => {
const eventId = context.params.eventId
if (!change.after.exists() && change.before.exists()) {
//data removed
days = change.before.val().dayofweek;
...
})

Can I treat items found through a Promise.all as a firebase collection?

I am stuck in what I thought was a very simple use case: I have a list of client ids in an array. All I want to do is fetch all those clients and "watch" them (using the .onSnapshot).
To fetch the client objects, it is nice and simple, I simply go through the array and get each client by their id. The code looks something like this:
const accessibleClients = ['client1', 'client2', 'client3']
const clients = await Promise.all(
accessibleClients.map(async clientId => {
return db
.collection('clients')
.doc(clientId)
.get()
})
)
If I just needed the list of clients, it would be fine, but I need to perform the .onSnapshot on it to see changes of the clients I am displaying. Is this possible to do? How can I get around this issue?
I am working with AngularFire so it is a bit different. But i also had the problem that i need to listen to unrelated documents which can not be queried.
I solved this with an object which contains all the snapshot listeners. This allows you to unsubscribe from individual client snapshots or from all snapshot if you do not need it anymore.
const accessibleClients = ['client1', 'client2', 'client3'];
const clientSnapshotObject = {};
const clientDataArray = [];
accessibleClients.forEach(clientId => {
clientSnapshotArray[clientId] = {
db.collection('clients').doc(clientId).onSnapshot(doc => {
const client = clientDataArray.find(client => doc.id === client.clientId);
if (client) {
const index = clientDataArray.findIndex(client => doc.id === client.clientId);
clientDataArray.splice(index, 1 , doc.data())
} else {
clientDataArray.push(doc.data());
}
})
};
})
With the clientIds of the accessibleClients array, i create an object of DocumentSnapshots with the clientId as property key.
The snapshot callback function pushes the specific client data into the clientDataArray. If a snapshot changes the callback function replaces the old data with the new data.
I do not know your exact data model but i hope this code helps with your problem.

Get the ChildrenCount of a child in Firebase using JavaScript

I have been doing this for an hour. I simply want to get the number of children in the child "Success" in the database below. The answers in similar stackoverflow questions are not working. I am new in Javascript Programming.
So far I have tried this
var children = firebase.database().ref('Success/').onWrite(event => {
return event.data.ref.parent.once("value", (snapshot) => {
const count = snapshot.numChildren();
console.log(count);
})
})
and also this
var children = firebase.database().ref('Success/').onWrite(event => {
return event.data.ref.parent.once("value", (snapshot) => {
const count = snapshot.numChildren();
console.log(count);
})
})
Where might I be going wrong.
As explained in the doc, you have to use the numChildren() method, as follows:
var ref = firebase.database().ref("Success");
ref.once("value")
.then(function(snapshot) {
console.log(snapshot.numChildren());
});
If you want to use this method in a Cloud Function, you can do as follows:
exports.children = functions.database
.ref('/Success')
.onWrite((change, context) => {
console.log(change.after.numChildren());
return null;
});
Note that:
The new syntax for Cloud Functions version > 1.0 is used, see https://firebase.google.com/docs/functions/beta-v1-diff?authuser=0
You should not forget to return a promise or a value to indicate to the platform that the Cloud Function execution is completed (for more details on this point, you may watch the 3 videos about "JavaScript Promises" from the Firebase video series: https://firebase.google.com/docs/functions/video-series/).
const db = getDatabase(app)
const questionsRef = ref(db, 'questions')
const mathematicalLiteracy = child(questionsRef, 'mathematicalLiteracy')
onValue(mathematicalLiteracy, (snapshot) => {
const data = snapshot.val()
const lenML = data.length - 1
console.log(lenML)
})
This method worked for me. I wanted to get the children's count of the mathematicalLiteracy node in my database tree. If I get its value using .val() it returns an array that contains that node's children and an extra empty item. So, I subtracted that one empty item's count. Finally, I get my needed children's count.

Cloud Function for Firebase Type Error - Cannot Read Property

I'm trying to write a Cloud Function that creates a record whenever someone uses our legacy app to create a record (we have changed the Firebase backend architecture and want to slowly migrate users). However, I'm getting the following error in my logs:
TypeError: Cannot read property 'update' of undefined
at exports.makeNewComment.functions.database.ref.onWrite.event (/user_code/index.js:14:92)
at /user_code/node_modules/firebase-functions/lib/cloud-functions.js:35:20
at process._tickDomainCallback (internal/process/next_tick.js:129:7)
Here is the script in question:
//required modules
var functions = require('firebase-functions');
const admin = require('firebase-admin');
// Listens for new comments added to /comments/ and adds it to /post-comments/
exports.makeNewComment = functions.database.ref('comments/{commentId}').onWrite(event => {
// Grab the current value of what was written to the Realtime Database.
const commentId = event.params.commentId;
const comment = event.data.val();
// You must return a Promise when performing asynchronous tasks inside a Functions such as
// writing to the Firebase Realtime Database.
//return event.data.ref.parent.child('post-comments').set(comment);
return functions.database.ref('post-comments/' + comment['postID'] + '/' + commentId).update(comment).then(url => {
return functions.database.ref('user-comments/' + comment['postedBy'] + '/' + commentId).update(comment);
});
});
//initialize
admin.initializeApp(functions.config().firebase);
Thanks!
You can't use functions.database.ref() in the middle of a function to get a ref to somewhere in your database. That's only for defining a new Cloud Function.
If you want a ref to somewhere in your database, you can use event.data.ref or event.data.adminRef to get a ref to the location where the event triggered. You could then use the root property of that to rebuild a new ref to somewhere else in the database. Or you can use your admin object to build a new ref.
It might be helpful to look at some sample code to get a sense of how things work.
Based on Doug's answer, you can replace functions.database.ref with event.data.ref.root.
var functions = require('firebase-functions');
const admin = require('firebase-admin');
exports.makeNewComment = functions.database.ref('comments/{commentId}').onWrite(event => {
const commentId = event.params.commentId;
const comment = event.data.val();
return event.data.ref.root.child('post-comments/' + comment['postID'] + '/' + commentId).update(comment).then(url => {
return event.data.ref.root.child('user-comments/' + comment['postedBy'] + '/' + commentId).update(comment);
});
});
admin.initializeApp(functions.config().firebase);

firebase - handle no data from snapshot

I have a firebase reference, where I pull data down for a specific custom index I created.
requestsRef
.orderByChild('systemgameindex')
.startAt(lastrequest.systemgameindex.toString())
.endAt(lastrequest.systemgameindex.toString() + '~')
.limitToFirst(customElem.dataops.limit + 1)
.on('child_added', function (snapshot) {
var request = snapshot.val() || {};
request.key = snapshot.key();
request.systemColor = customElem.getSystemColor(request.system);
request.description = customElem.truncateText(request.description, 65);
customElem.getUserProfile(request);
customElem.getCommentCount(request.key);
if (request.systemgameindex !== lastrequest.systemgameindex) { customElem.push('requests', request); };
customElem.removeSpinnerRoo();
});
Right before I make the call to firebase, I have a custom spinner I dislay with a function called addSpinnerRoo(), and when data is returned, I make a call to removeSpinnerRoo() to hide the spinner on the DOM.
It works beautifully when there's data to return from firebase, but if the firebase query brings back no results, the callback on child_added never gets fired, so I have a spinner still spinning on the DOM.
Is there a way to handle when there's no data returned within Firebase?
Any insight would be appreciated a lot. Thanks
After reading this from the documentation from here:
The callback function receives a DataSnapshot, which is a snapshot of the data. A snapshot is a picture of the data at a particular database reference at a single point in time. Calling val() on a snapshot returns the JavaScript object representation of the data. If no data exists at the reference's location, the snapshots value will be null.
I was able to do use "val" instead of "child_added" to actually have firebase still fire the callback for the ".on()" method. So my code now looks like this:
var data = snapshot.val();
if (data !== null && data !== undefined) {
var requests = _.map(data, function (val, key) {
val.key = key;
return val;
});
_.each(requests, function (request) {
request.systemColor = customElem.getSystemColor(request.system);
request.description = customElem.truncateText(request.description, 65);
customElem.getUserProfile(request);
customElem.getCommentCount(request.key);
customElem.push('requests', request);
});
}
customElem.removeSpinnerRoo();
And with that, I was able to get what I needed. If this helps anyone, great...

Categories

Resources