React Native Expo with Firebase: DataSnapshot is object not array - javascript

I have some simple data that looks like this, stored in a realtime database of firestore by calling update() and adding in an array as paremeter.
The game is generated by creating an array here and setting it in the "participants" field:
generateNewGame(code, name) {
this.database.ref().update({
[code]: { participants: [name] },
});
}
Now it is time to read the data, this is done by this method setting up a listener:
function setupRegisteredUsersListener() {
FirebaseService.getDatabaseReference(
"/" + codeRef.current + "/participants"
).on("value", (snapshot) => {
if (snapshot.val()) {
// setUsers(snapshot.val());
console.log(typeof snapshot.val());
console.log(JSON.stringify(snapshot.val(), null, 4));
}
});
}
Even though I stored the data as an array, and it LOOKS like an array, the type is Object. How can I circumvent this behaviour, or do I have to manually convert the object to an array somehow?
The documentation, says the .val() function should be able to convert the DataSnapshot into an array. But apparently that is not the default in my case.
The output from the function looks like this:
So obviously the daya is ALMOST an array, but not quite.

Do I have to manually convert the object to an array somehow?
No, you can directly use the value returned by snapshot.val() as an Array.
Array.isArray(snapshot.val()) will return true.
Also, for example, the following will return 0
console.log(snapshot.val().findIndex((element) => element === 'Hej'));
Or, if you add another element, the following will print the values of the two elements
console.log(snapshot.val()[0]);
console.log(snapshot.val()[1]);

Related

Access the second item in Collection [Map]

I'm making a discord bot, and fetching some messages. I got this object
//This parameters changue every time i fetch
Collection(3) [Map] {
'848689862764789770' => Message {...
}
'848689552410804234' => Message {...
}
'848689534485004319' => Message {...
}
I can access the first and third entry using .first() and .last().
I've been trying to use Object.keys() but it returns undefined.
const mensajes = await message.channel.messages.fetch({ limit: 3 });
console.log(mensajes[Object.keys(mensajes)[1]])
Tip:
.first() can take a parameter that will return the first x amount of entries you choose and will then convert the Collection into an Array. Do .first(2) - this will return the first 2 entries - and then access the 2nd element as you would with any other Array.
// Will return 2nd entry
<Collection>.first(2)[1]
Suggested Solution:
You can also call .array() on the Collection to directly convert it into an Array.
// Also returns 2nd entry
<Collection>.array()[1]
<Collection> is a placeholder for your actual object
Learn more about working with Collections in This Guide
DiscordJS's docs has some information on this. You can transform this Collection utility class intro an array with a bunch of methods that exist for it, depending on what you need to access.
Then you can use the array, for example, to access the specific value.
// For values. Array.from(collection.values());
// For keys. Array.from(collection.keys());
// For [key, value] pairs. Array.from(collection);

Getting empty snapshot when reading Firebase Database in Javascript?

I have the following database structure:
I am trying to get the list of values under registrationTokens to then execute an FCM notification to the list of tokens. But the output to the console is empty even though there is a token under the child node. Am I missing something here?
Console output:
registrationTokens [ '0' ]
Part of my JS function code below:
return admin.database().ref('/fcmtokens/' + toId + '/registrationTokens').once('value').then((userTok) => {
const registrationTokens = Object.keys(userTok.val());
console.log('registrationTokens', registrationTokens);
});
Your console output is exactly as I'd expect. You've read the following children from the database:
0: 'c4P...'
Then you asked for the keys of that object to be printed, as returned by Object.keys(). Note that this key a key/value pair: the key is 0 and the value is 'c4P...'. This means that the following call:
Object.keys(userTok.val());
Is going to return an array of keys of the children. Since there is one child with a key of 0, you get this array:
[ '0' ]
So, I'd say your function is working exactly as you coded it. If you want the token values instead, try this:
If you want to tokens for each key instead, maybe you should use Object.values() instead:
Object.values(userTok.val());
I'd expect that to return an array of all the values associated with they keys.

Javascript string/object/array confusion with JSON

I'm having a Laravel backend return some errors via Validator. These errors are passed through a HTTP response made by angular, and returned in JSON format.
The object is structured as seen below:
That name object has a value, which is the actual message that I'm after.
Currently, using loops etc., I can only get the name of the array (name) as a string...
I sometimes get multiple arrays within this error object, and I won't always know their names, so how may I retrieve that 0-index value in each of them, in a loop?
Thanks for any help.
Edit #1
Looping through it like this:
for(var err in res.data.errors){
console.log(Object.err[0][0]);
}
Gives me a Cannot get [0] index of undefined
How about this:
let errors = Object.values(response.data.errors);
// errors is now an array of arrays containing the validation errors
errors.forEach( (errorArray) => {
console.log(errorArray[0]);
} );
Another approach would be using Object.keys() instead of values. This is similar to what you already tried, where you get the name of the error property as a string, and then use it to access each error array:
let keys = Object.keys(response.data.errors);
keys.forEach( (errorKey) => {
console.log('error type', errorKey);
let errorArray = response.data.errors[errorKey];
console.log(errorArray[0]);
} );

Using Filter Function to Return List of Filtered Results from API

In one view I am pulling an array of client records from our mongoDB/Node-based API and printing them to the screen in my Angular app. Now I want to create another view where a filtered list of those records are returned.
Specifically I want to return a list of client records that have a value on the object for the property "exitDate". The idea here is that if there IS an exitDate (i.e. the value is not null), then this means the record is an "inactive" result.
The original collection of records are being generated via an observable in the OnInit life cycle, like this:
this.clientService.getAll()
.subscribe(resRecordsData => this.clients = resRecordsData,
responseRecordsError => this.errorMsg = responseRecordsError);
So to do this I'm trying to use a filter function. This is what I have:
isInactive() {
this.inactiveClients = this.clients.filter(exitDate => !!exitDate);
}
Can one handle it this way? Will this filter function return objects that have a value for the property "exitDate" and exclude those that don't?
You are almost right, but the filter function will give you as an argument each one of the objects and you'll need to look for the property and its value, so it would be something like this:
this.clients.filter(client => client.exitDate !== null);
The array's filter method walks the array and executes the callback for each of its items, so the first argument you get on the callback is the item itself.
In this case, you want to check for the exitDate property and return 'true' if it is not null.

How To Efficiently Extract Certain Information From A POJO

I am working a lot with firebase, and am trying to load certain information from the database. The original data comes from a query, and is returned to me in a POJO. The console prints this when the original data is returned:
-KhQ76OEK_848CkIFhAq: "-JhQ76OEK_848CkIFhAq"
-OhQ76OEK_848CkIFhAq: "-LhQ76OEK_848CkIFhAq"
What I need to do is grab each of the values (-JhQ76OEK_848CkIFhAq and -LhQ76OEK_848CkIFhAq) separately, and query the real-time database again for each one. I can manage that aspect, but I cannot seem to figure out how to separate the values.
I have already tried to get a single output by doing:
console.log(vals[0]) but it just returned undefined, and splitting the string by " would be very inefficient for large data sets. Any ideas?
To access the values, you can iterate the snapshot's children using the snapshot's forEach method. The keys and values of the children can be obtained using the key property and the val() method:
firebase.database()
.ref("some/path")
.once("value")
.then((snapshot) => {
snapshot.forEach((childSnapshot) => {
console.log(childSnapshot.key); // The child's key: e.g. "-KhQ76OEK_848CkIFhAq"
console.log(childSnapshot.val()); // The child's value: e.g. "-JhQ76OEK_848CkIFhAq"
});
});
To solve this issue, all I did was convert the object returned into an array by using this code below:
var Array = Object.keys(datalist).map(function(k) { return datalist[k] });
Works like a charm, and I can now run a simple for loop for Array

Categories

Resources