React, Firebase: Access values of JSON and also get key value - javascript

I am beginner working with firebase, react. I am able to get the required data from firebase based on userEmail. But I am very confused in accessing the data.
firebase.database().ref('/users').orderByChild('email').equalTo(userEmail).on('value', data => {
console.log('data: ', data);
})
I get the following output:
data: Object {
"-Lhdfgkjd6fn3AA-": Object {
"email": "t5#gmail.com",
"favQuote": "this is it",
"firstName": "t5",
"lastName": "l5",
},
}
Please help me how to access all values ("-Lhdfgkjd6fn3AA-" , firstname, lastname, email and favQuote) into variables like: data.firstName, data.lastName, data.key, etc . Thank you.

let data = {
"-Lhdfgkjd6fn3AA-": {
"email": "t5#gmail.com",
"favQuote": "this is it",
"firstName": "t5",
"lastName": "l5",
},
};
console.log(Object.keys(data))//returning an array of keys, in this case ["-Lhdfgkjd6fn3AA-"]
console.log(Object.keys(data)[0])
console.log(Object.values(data))//returning an array of values of property
console.log(Object.values(data)[0].email)
Do need to be careful that the above code with the hardcoded "0" as index because it assumed that your data object has only one key. If you have more key, you can't simply replace index either because property of object has no predictable sequence

It's really a JavaScript question. I had to figure this out too. ...this works.
var p;
var thisLine;
p = docu.data();
for (var k in p) {
if (p.hasOwnProperty(k)) {
if (isObject(p[k])) {
thisLine = p[k];
Object.keys(thisLine).forEach(function (key, index) {
console.log(key, index);
});
}
}
}
function isObject(obj) {
return obj === Object(obj);
}

When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
So your first step is that you need to loop over the snapshot in your on() callback.
The second step is that you need to call Snapshot.val() to get the JSON data from the snapshot. From there you can get the individual properties.
firebase.database().ref('/users').orderByChild('email').equalTo(userEmail).on('value', snapshot => {
snapshot.forEach(userSnapshot => {
let data = userSnapshot.val();
console.log('data: ', data);
console.log(data.email, data.firstname);
});
})

Related

How to push an item to the array inside JSON Object?

I am trying to make inventory functionality using Discord.js and struggling on how to push an item to the array inside JSON Object.
Inside the JSON, every user with unique 'userID' has their own array 'inventory'.
The thing I want to achieve is:
After user types 'get' command in the chat, the item is pushed to the inventory array and the JSON file is updated.
.json file:
{
"userID": {
"inventory": []
}
}
.js file:
const item = itemName
inventory[userID] = {
inventory: inventory[userID].inventory + item,
}
fs.writeFile('./data/inventory.json', JSON.stringify(inventory), err => {
if (err) console.log(err)
})
Output (after using command twice):
{
"userID": {
"inventory": ["itemNameitemName"]
}
}
Expected output (after using command twice):
{
"userID": {
"inventory": ["itemName", "itemName"]
}
}
The thing I want to achieve is: After user types 'get' command in the chat, the item is pushed to the inventory array and the JSON file is updated. I suppose I need to use .push() somewhere, but I tried it million times in all configurations I could think of and it always throws an error, that .push() is not a function.
Instead of making a new object for the user every time you want to update the inventory, it would be much easier if you can just push the item to the inventory instead of reassigning. #DanielAWhite wrote the correct solution but I think you misunderstood where to put that particular piece of code. What you might have tried is this:
const inventory = {
"userID": {
"inventory": ["testOne"]
}
}
const item = "test"
const userID = "userID"
inventory[userID] = {
inventory: inventory[userID].inventory.push(item),
}
console.log(inventory)
Instead, what the correct way was to do away with the inventory[userID] = {} part and just directly push the item to the inventory by doing this:
const inventory = {
"userID": {
"inventory": ["testOne"]
}
}
const item = "test"
const userID = "userID"
inventory[userID].inventory.push(item)
console.log(inventory)
(Note: I edited the code a little bit so that you could try to run this code right here, but this should work with your fs.writeFile as well
Try this :
let rawdata = fs.readFileSync('inventory.json');
let inventory = JSON.parse(rawdata);
inventory["userID"] = {
inventory: [...inventory["userID"].inventory, item],
}
fs.writeFile('./inventory.json', JSON.stringify(inventory), err => {
if (err) console.log(err)
})

forEach not a function when index starts at anything but 0

When inside an object there isn't an index that starts with 0, it returns:
TypeError: data.forEach is not a function
This is how the database looks:
If I add an object with the index 0 to the database, like so (my formatting doesn't matter, this is just to illustrate the hierarchy):
0: {
email: "testmail",
uid: "testuid"
}
Suddenly the forEach function works and also retrieves the users with index 3 and 4. How can I make the forEach loop start at index 3 for example? Or is there a different method that I should be using instead? My code:
useEffect(() => {
if(props.klasData.gebruikers !== undefined) {
var data = props.klasData.gebruikers;
data.forEach(function (user) {
if(!emails.hasOwnProperty(user.email)) {
addEmail(oldArray => [...oldArray, user.email]);
}
setPending(false)
})
}
}, []);
Edit
props.klasData.gebruikers returns all keys within the "gebruikers" object with their children.
It looks like your data is being interpreted as an array by the Firebase SDK, since it starts with sequential numeric keys. If you print the value of your gebruikers snapshot, you'll see that it's:
[null, null, null, {email: "test", uid: "test"}, {email: "wouter#...", uid: "..."}]
These null values are added by the Firebase SDK to turn the keys into a proper array.
If you want to keep the Firebase SDK from converting the data into an array, prefix the keys with a non-numeric character. For example:
"key2": {email: "test", uid: "test"},
"key3": {email: "wouter#...", uid: "..."}
In general, it is more idiomatic to use the UID of the users as the keys in a collection of users. That way, you won't need to query for the UID, and you're automatically guaranteed that each user/UID can only be present in the collection one.
I changed the database like you can see here, as Frank van Puffelen suggested. As Frank also predicted, the root of my problem was coming from the function I didn't post.
By transforming all the indexes of UIDs I was fetching from the database to sequential numeric keys, I managed to get the forEach function working. I did this using users = Object.values(users).filter((el) => {return el != null}). The full effect hook can be found below:
useEffect(() => {
var refCodes = firebase.database().ref("userdata/" + currentUser.uid + "/docentCodes").orderByKey();
refCodes.once("value").then(function (snapshotCodes) {
snapshotCodes.val().forEach(function (code) {
var refCodeData = firebase.database().ref("klassencodes/" + code).orderByKey();
refCodeData.once("value").then(function (snapshotCodeData) {
var users = snapshotCodeData.val().gebruikers;
users = Object.values(users).filter((el) => {return el != null})
if(snapshotCodeData.val() !== null) {
setUsercount(oldArray => [...oldArray, users.length]);
setKlasData(oldArray => [...oldArray, snapshotCodeData.val()]);
setUserdata(oldArray => [...oldArray, users]);
addCode(oldArray => [...oldArray, code])
}
setPending(false);
})
})
})
}, []);
In the function where this useEffect is used, I added const [userdata, setUserdata] = React.useState([]); to acommodate this new information stripped down from indexes of UIDs to indexes made of numeric keys. This userdata is exported to another function, which has the effect hook as stated in the original question. I changed this up to be:
useEffect(() => {
if(props.userData !== undefined) {
var data = props.userData;
if(data !== undefined) {
data.forEach(function (user) {
if(!emails.hasOwnProperty(user.email)) {
addEmail(oldArray => [...oldArray, user.email]);
addUID(oldArray => [...oldArray, Object.keys(props.klasData.gebruikers)]);
}
setPending(false)
})
}
}
}, []);
Summary
In retrospect, I should've gone with a seperate const for just the userdata (snapshotCodeData.val().gebruikers), seperate from the other data returned from the snapshot (snapshotCodeData.val()).
I hope this may help you. The golden line of code is users = Object.values(users).filter((el) => {return el != null}).

Accessing Firebase data in a node with JS

So I have an object being returned from Firebase that looks like this:
{key: {name: "test", email: "test", id: "test"}}
How can I get the id out of this object?
If I do returnItem I get that object, so I tried to do returnItem[0] but it's not an array, and I've tried (Object.keys(tempSnap) but that just gives me the key not the object inside it.
This is my current code:
export function sendInvitation(email) {
firebaseRef.database().ref().child('users').orderByChild('email').equalTo(email).on("value", function(snapshot) {
let tempSnap = snapshot.val();
if(tempSnap != null) {
console.log(tempSnap);
}
});
return dispatch => firebaseRef.database().ref(`${userID}/invites`).push("This is a test Message!");
}
This is what it outputs:
Help would be awesome :D
If you already know id and it's a literal, then it's a matter of returnItem.id.
If you already know id and it's a variable, then it's returnItem[id].
If you don't know the keys and want to print all keys and their values, it's:
Object.keys(returnItem).forEach(function(key) {
console.log(key, returnItem[key]);
});
Update
Your new code shows the problem. When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result. Your callback needs to handle the fact that it gets a list by looping over the results with snapshot.forEach():
firebaseRef.database().ref().child('users').orderByChild('email').equalTo(email).on("value", function(snapshot) {
snapshot.forEach(function(child) {
let tempSnap = child.val();
console.log(tempSnap);
});
});
Try this:
firebaseRef.database().ref().child('users').orderByChild('email').equalTo(email).on("value", function(snapshot) {
snapshot.forEach(function(child) {
let keys=child.key;
let ids=child.val().id;
)};
)};
you have:
users
keyid
email:email
name:yourname
id: test

Extract data from API Object in React

I'm trying to retrieve data from an API with the following JSON output and I have a function in react that I call.
I can see the api output in console.log(users) so the data is being passed into the function.
I am trying to output the array contained in "data" but can't seem to access the data.
{
"dataCount": 2,
"data": [
{
"name": "Test review header",
"text": "This is adescription for a test review",
"img": "http://pngimg.com/upload/pigeon_PNG3423.png"
},
{
"name": "Test review header2",
"text": "This is adescription for a test review2",
"img": "http://pngimg.com/upload/pigeon_PNG3422.png"
}
]
}
renderUsers() {
const { users } = this.props;
console.log(users);
Object.keys(users).map(name => users[name])
console.log(users[name]);
};
The data you need to iterate over is present in the data field of users.
When you are using lists you have to specify the key property, to make react keep track of each item in list.
renderUsers() {
const { users } = this.props;
return (
<ul>
{
users.data.map(name => {
<li key={name}>users[name]</li>
})
}
</ul>
)
}
First of all, I don't use react but what you want should be the same in other javascript frameworks.
Are you sure that it is JSON you receive?
We need to be sure that you receive a JSON object and not normal text. Lets say you have a function parseResponse(data). We can call JSON.parse(data) to parse the data param to a json object. It is also possible that you store the result in a variable.
Using the JSON object
When we are sure you have the param parsed to a JSON object, we get it's data. For example, if you want to get the name of the first object in data, you can call:
parsedJson.data[0].name
where parsedJson is the result of JSON.parse(data),
data is an array of objects in the JSON,
0 is the first object in the array
It is possible that you have this kind of function then:
function parseResponse(data) {
var parsedJson = JSON.parse(data);
for(var i = 0; i < parsedJson.data.length; i++) {
console.log(parsedJson.data[i].name);
}
}
see jsfiddle

firebase - Get the uniqe push ID

I want to get the unique ID of push method for this data:
{
"users": {
"-KKUmYgLYREWCnWeHDfT": {
"fName": "Peter",
"ID": "U1EL9SSUQ",
"username": "peter01"
},
"-KKUmYgLYREWCnWeHCvO": {
"fName": "John",
"ID": "U1EL5623",
"username": "john.doe"
}
}
}
Since name() has been deprecated I tried to use .key, but it returned not the unique ID, but the users key instead.
ref.child("users").orderByChild("ID").equalTo("U1EL9SSUQ").once("value", function (snapshot) {
console.log("KEY: " + snapshot.key); // snapshot.key === users
});
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
By calling snapshot.key you are getting the name of the node on which the query was executed. The deprecated snapshot.name() would have done the exact same thing.
To get the key of the matches item, you need to loop over the snapshot's children:
ref.child("users")
.orderByChild("ID")
.equalTo("U1EL9SSUQ")
.once("value", function (snapshot) {
snapshot.forEach(function(child) {
console.log("KEY: " + child.key);
});
});
You need to use .val() to extract a Javascript value from a DataSnapshot. The following should work.
ref.child("users").orderByChild("ID").equalTo("U1EL9SSUQ").once("value", function (snapshot) {
console.log("KEY: " + Object.keys(snapshot.val())[0]);
});

Categories

Resources