Can't get object key in firebase - javascript

Problem: I am making an app with Firebase and React Native where users can post, and then other users can comment on posts. To do the comments, I need to grab the key of the content of a post. I tried using the child.getKey() function, but that gave me an error.
child.getKey is not a function. (In 'child.getKey()', 'child.getKey' is undefined)
I would really love some help getting the key. Thank you!
Code
getItems(){
var items = [];
var query = ref.orderByKey();
query.once ('value', (snap) => {
snap.forEach ( (child) => {
items.push({
content: child.val().content,
key: child.getKey()
});
});
items.reverse();
}).then(() => {
this.setState({firebaseItems: items});
});
}
Firebase layout
Posts:
-Kier498dma39md:
content: 'This is an example post. The numbers above me are an example of the random key I am trying to get.'

So, I did some research, and eventually found out all I needed to do was use key: child.key

Related

Realtime database query and react native

I'm quite new to performing firebase realtime database queries and react native. I have a list of users in my realtime database and some of the users have a list of properties as shown below. I would like to obtain these properties as well as the users of the properties and place it into an array using react native. I'm not to sure how to do this.
This is what I have so far:
database().ref(`users/`).once(`value`, snapshot =>{
snapshot.forEach(function(childSnapshot){
if(childSnapshot.val().properties != null) {
}
});
I would like the error to be displayed as:
[{uid1,property1}, {uid1,property2}, {uid2,property1}, {uid2,property2}, {uid2,property3},...., {uidX,propertyX}]
})
I find that in cases like this, it really helps to give your variables good names:
database().ref(`users/`).once(`value`, snapshot =>{
let properties = [];
snapshot.forEach((userSnapshot) => {
if (userSnapshot.hasChild("properties")) {
userSnapshot.child("properties").forEach((propertySnapshot) => {
properties.push({
uid: userSnapshot.key,
property: propertySnapshot.val()
})
})
}
});
console.log(properties);
});

How to insert data into mysql using angular and nodejs - getting (NULL, NULL) upon insert - Problem solved

Good day,
I've been trying to learn a bit of angular and nodejs. I found a tutorial on a realtime chat app and made some few adjustment to some function of the code. But the one aspect that I cannot seem to get right is the ability for the user to post to a feed. The login process works, the user is already logged in but the user can't post. I would also like to be able to get all they data i insert from all the user to show up like a normal feedview will. Please assist.
Here are my files:
FROM MY CONTROLLER HERE IS THE CODE WHEN THE BUTTON IS PRESSED
$scope.postDatatoDd = () => {
appService.httpCall({
url: '/posts',
params: {
'posts': $scope.data.info,
'from_user_id': $scope.data.username
}
})
.then((response) => {
// $scope.$apply();
})
.catch((error) => {
alert(error.message);
});
}
and here is my route file:
this.app.post('/posts', async(request,response) => {
const reqResponse = {}
const data = {
posts : request.body.postDatatoDd,
from_user_id: request.body.username
};
if (data.posts === ''){
reqResponse.error = true;
reqResponse.message = `error, input`;
response.status(412).json(reqResponse);
} else {
const result = await helper.insertFeed(data);
if (result === null) {
reqResponse.error = true;
reqResponse.message = `they was an error.`;
response.status(417).json(reqResponse);
} else {
reqResponse.error = false;
reqResponse.userId = result.insertId;
reqResponse.message = `posted succesfully`;
response.status(200).json(reqResponse);
}
}});
and in my helper file there is this function to insert data:
async insertFeed(params){
try {
return await this.db.query(
`INSERT INTO posts (from_user_id,posts) values (?,?)`,
[params.from_user_id,params.postDatatoDd]
);
} catch (error) {
console.warn(error);
return null;
}
}
On the client side here is the button with :
<label for="postDatatoDd">Post</label>
<input type="text" id="postDatatoDd"
ng-model="data.postDatatoDd"
class="feed form-control"
placeholder="post your data here?"
/>
<button ng-click="postDatatoDd()" class="btn btn-primary">Post</button>
</div>
--- EDIT 1---
Data is being inserted now, but it is receiving the values as (NULL, NULL).
--- EDIT 2 ---
After closely looking at the code and fixing some naming variables the code works fine, the data is being inserted in mysql as it should.
Other than a lot of typos when it comes to the variables reference. The code seem to be fine.
Assuming that you using appservice class somewhere in your code and its functioned, then everything else will work.
You are getting the (NULL, NULL) because you are parsing parameters that are not being properly parsed out to your helper file, please close attention to that.
appService
.httpCall({
url: "/posts",
params: {
posts: $scope.data.postbuzz,
from_user_id: $scope.data.username,
},
})
.then((response) => {
$scope.$apply();
})
.catch((error) => {
alert(error.message);
});
make sure that the data that you calling from this above function is similar to $scope parameter you passing in your route file that your requesting:
const data = {
posts : request.body.posts,
from_user_id: request.body.from_user_id}
and in your database helper class you running:
`INSERT INTO posts (from_user_id,post) values (?,?)`,
[params.from_user_id,params.posts]
Hope this was helpful
You seem to have an understand already. your question may help a lot more people in the future.
params should be as following, since the data object has properties from_user_id and posts
`INSERT INTO posts (from_user_id,posts) values (?, ?)`,
[params.from_user_id,params.posts]
Might be useful https://www.w3schools.com/nodejs/nodejs_mysql_insert.asp
--- EDIT 2 ---
After closely looking at the code and fixing some naming variables the code works fine, the data is being inserted in mysql as it should.
If you are new to Angular you can use the code as reference.

Discord.js How to get description of reddit post

I have this code where it gets a random post from r/memes and it get's the post's title with an image attached to it(if there is one), I got this with a lot of help and I just want it to be able to read the post's description. I want to be able to read the text if there is some in the post if I want to use this on like news subreddits or something.
if (msg.content == '-meme') {
function loadMemes() {
// Fetch JSON
return (
fetch('https://www.reddit.com/r/memes.json?limit=800&?sort=hot&t=all')
.then((res) => res.json())
// Return the actual posts
.then((json) => json.data.children)
);
}
function postRandomMeme(message) {
return loadMemes().then((posts) => {
// Get a random post's title and URL
const { title, url } = posts[Math.floor(Math.random() * posts.length)].data;
// Create the embed
const embed = new Discord.RichEmbed({
title,
image: { url },
footer: { text: 'Subreddit : r/memes' },
});
// Send the embed
return message.channel.send(embed);
});
}
// Usage:
postRandomMeme(msg);
// Log all errors
//.catch(console.error);
}
There is a github repository called reddit-bot which is open source and online. you can possibly get an idea from the code provided on there.
https://github.com/lowJ/reddit-bot/blob/master/index.js
I also found this npm package specifically made to get memes and also has an open source github repository.
https://www.npmjs.com/package/#blad3mak3r/reddit-memes

Nesting API calls and mapping to same returned object ES6 / ReactJs

I'm just starting out with React and ES6 so apologies if this is a bit of a simple one.
I'm currently playing round with the FoursquareAPI. I'm using ES6 fetch to return a series of objects (they're actually different venues in different parts of the world) which are then mapped and returned and stored in the application's state. This works fine and returns what I want:
// method to call api
getVenues: (searchTerm) => {
const fetchVenuesURL = `${urlExplore}${searchTerm}&limit=10&client_id=${clientId}&client_secret=${clientSecret}&v=20180602`;
return fetch(fetchVenuesURL).then( response => {
return response.json();
}).then( jsonResponse => {
if (jsonResponse.response.groups[0].items) {
return jsonResponse.response.groups[0].items.map(item => (
// populate venues
{
id: item.venue.id,
name: item.venue.name,
address : item.venue.location.address,
city : item.venue.location.city,
country : item.venue.location.country,
icon : item.venue.categories[0].icon
}
));
} else {
return [];
}
});
// method in App.js to setState
search(term){
Foursquare.getVenues(term).then(foursquareResponse => {
this.setState({venues: foursquareResponse});
});
}
The problem arises when I need to fetch photographs associated with each of the 'venues' returned by the original fetch. These come from a different endpoint. I'm not sure what the best approach is.
One way would be to have two separate api calling methods and then somehow populate an empty photos field of the first with the photos from the second back in App.js but that seems clunky.
My instinct is to somehow nest the Api calls but I'm uncertain about how to go about this. I'm hoping to do something along the lines of somehow applying a method to each iteration of the first mapped object, something along the lines of but not sure how to link them together so that the second goes into the photo property of the first:
{
id: item.venue.id,
name: item.venue.name,
address : item.venue.location.address,
city : item.venue.location.city,
country : item.venue.location.country,
icon : item.venue.categories[0].icon
photos : []
}
const fetchPhotosURL = `${urlPhotos}${venueId}/photos?limit=10&client_id=${clientId}&client_secret=${clientSecret}&v=20180602`;
return fetch(fetchPhotosURL).then( response => {
return response.json();
}).then( jsonResponse => {
if (jsonResponse.response.photos.items) {
console.log(jsonResponse.response.photos.items[0].venue)
return jsonResponse.response.photos.items.map(item => (
{
id : item.id,
created: item.createdAt,
prefix: item.prefix,
suffix: item.suffix,
width: item.width,
height: item.height,
venue: item.venue
}
));
} else {
return [];
}
})
Can anyone point me in the right direction with this. I'm guessing that it's one of those things that isn't that hard once you've done it once but I'm finding it difficult.
Thanks in advance.

Firebase React Binding

I'm somewhat new to React, and using the re-base library to work with Firebase.
I'm currently trying to render a table, but because of the way my data is structured in firebase, I need to get a list of keys from two locations- the first one being a list of user keys that are a member of a team, and the second being the full user information.
The team node is structured like this: /teams/team_id/userkeys, and the user info is stored like this: /Users/userkey/{email, name, etc.}
My table consists of two react components: a table component and a row component.
My table component has props teamid passed to it, and I'm using re-base's bindToState functionality to get the associated user keys in componentWillMount(). Then, I use bindToState again to get the full user node, like so:
componentWillMount() {
this.ref = base.bindToState(`/teams/${this.props.data}/members`, {
context: this,
state: 'members',
asArray: true,
then() {
this.secondref = base.bindToState('/Users', {
context: this,
state: 'users',
asArray: true,
then() {
let membersKeys = this.state.members.map(function(item) {
return item.key;
});
let usersKeys = this.state.members.map(function(item) {
return item.key;
});
let onlyCorrectMembersKeys = intersection(membersKeys, usersKeys);
this.setState({
loading: false
});
}
});
}
});
}
As you can see, I create membersKeys and usersKeys and then use underscore.js's intersection function to get all the member keys that are in my users node (note: I do this because there are some cases where a user will be a member of a team, but not be under /Users).
The part I'm struggling with is adding an additional rebase call to create the full members array (ie. the user data from /Users for the keys in onlyCorrectMembersKeys.
Edit: I've tried
let allKeys = [];
onlyCorrectMembersKeys.forEach(function(element) {
base.fetch(`/Users/${element}`, {
asArray: true,
then(data) {
allKeys.prototype.concat(data);
}
});
});
But I'm receiving the error Error: REBASE: The options argument must contain a context property of type object. Instead, got undefined
I'm assuming that's because onlyCorrectMembersKeys hasn't been fully computed yet, but I'm struggling with how to figure out the best way to solve this..
For anyone dealing with this issue as well, I seemed to have found (somewhat) of a solution:
onlyCorrectMembersKeys.map(function(item) {
base.fetch(`/Users/${item}`, {
context: this,
asObject: true,
then(data) {
if (data) {
allKeyss.push({item,data});
this.setState({allKeys: allKeyss});
}
this.setState({loading: false});
},
onFailure(err) {
console.log(err);
this.setState({loading: false});
}
})
}, this);
}
This works fine, but when users and members state is updated, it doesn't update the allkeys state. I'm sure this is just due to my level of react knowledge, so when I figure that out I'll post the solution.
Edit: using listenTo instead of bindToState is the correct approach as bindToState's callback is only fired once.

Categories