Change the state of component not working


#1

Hi guys, I need some help with something that seemed to be simple but proved not to be, I mean, I tried in several ways and nothing seems to work.

What I’m looking for:

  1. Save with the Love button, a new sub-collection with the necessary fields including recipient and sender email - DONE
  2. Send a message to the author of the comment via the cloud function for each new interaction - DONE
  3. Now that we have the data, use a script that changes the state of the button to {1} if the user has already contributed, I mean button heart turns red . FAILED

What I tried, considering that the [button comp] is inside list component with the comments listed
[Edit template] with a code

_updateItems = (docKey) => {
const db = firebase.firestore ();
const collection = db.collection (Userposts / $ {docKey} / loveComments) .orderBy (‘dateString’, ‘desc’);
this._cancelSnapshot = collection.onSnapshot (
and so on…
(nothing happens)


#2

HI, I’m not an Firestore expert but could this work? https://stackoverflow.com/questions/57231519/get-information-if-the-feed-is-liked-by-the-user-in-a-single-query-firestore

Storing likes (user id’s) in Array for each comments and then check if user id exists in array for each post? This would save of reads (money) when app scales.


#3

Hey Antti. Yes, perfect! that’s I’m trying this morning, inspired by your Cars finder.
Let’s try this approach.
Many thanks.


#4

The question would be, how to save with RS an array within each post containing the userID’s of the users who liked the post? I mean for each like inside the field ‘userLike’ like is stored in the Cars Finder Category column.

Looking at the link you shared, it seems as much as I could understand, it’s feasible retrieving and checking the existence of its id in each post user Likes array.

BTW, my initial approach was saving for each like, create then a sub collection and doc for each like. Then using Clould Function, based on the collect data send to Post Author an email message and notification.
This may impact costs of reading FB.

Maybe, if I can store the email of the userLike I would change the strategy and save readings simple FB trigger each time a new Array is created.


#5

Hi Annti. Hope you help me with this? Now that I’m able to store data in Array for each like. Any trick on how might I check if user id exists in Array for each post?
This is how data is stored in Firestore [{“userEmail”:“somebody@gmail.com”}]

Best regards


#6

I’m not able to check this now on computer but I would guess that you can simply loop Through the array to check if email is found in array.

Anyway I’d suggest to use user id rather than user email. Email might change over time and then you need to do some maintenance in db.


#7

Thank you Antti. I’ve tried the loop using RS reading an array field, but it keep returning 0.


#8

Hi. This is my last best shot, but it keeps returning looking at the console “No matching documents”
Hope

let transformPropValue_emailRef = (input) => {
const db = firebase.firestore();
let userRef = this.props.appActions.dataSlots[‘ds_SlotUserID’];
let userLikes = db.collection(‘postComments’)
let query = userLikes.where(‘likes’, ‘array-contains’, [{userRef}])
.orderBy(‘dateString’, ‘desc’)
.get()
.then(snapshot => {
if (snapshot.empty) {
console.log(‘No matching documents’);
return;
}
snapshot.forEach(doc => {
console.log(doc.id, ‘=>’, doc.data());
});
})
.catch(err => {
console.log(‘Error getting documents’, err);
});

  return input;
}

#9

Have you tried to build the query without using the Data slots? I’d first test to build the query “manually” and when I know it works then add dynamic values (data slots).


#10

Yes, and the console will ask you to build an index in Firestore, which I did.

Finally I’m getting some results! But is not perfect returning five lines I guess. weird!

Good script:

const db = firebase.firestore();
let emailRef = this.props.appActions.dataSlots[‘ds_SlotUserEmail’];
let postID = this.props.appActions.dataSlots[‘ds_SlotpostID’];
let userLikes = db.collection(Userposts/${postID}/postComments)
let query = userLikes.where(‘likes’, ‘array-contains’, {userEmail: emailRef})
.orderBy(‘dateString’, ‘desc’)
.get()
.then(snapshot => {
if (snapshot.empty) {
console.log(‘No matching documents.’);
return;
}
snapshot.forEach(doc => {
console.log(doc.id, ‘=>’, doc.data());
});
})
.catch(err => {
console.log(‘Error getting documents’, err);
});

pHBO80NMBZvwGITw4mVc =>

  1. {NeighborhoodsID: “6tf5lYk7N3v5F6lk3M14”, author: “Marcos C. Alencar”, comment: “Testing”, commenterPhoto: “https://lh3.googleusercontent.com/a-/AAuE7mDMpdVCic53F1pSMRr3gCCDpk77MPLXwPSjTfC9Qg”, dateString: 1583874078715, …}

  2. NeighborhoodsID: “6tf5lYk7N3v5F6lk3M14”

  3. author: “Marcos C. Alencar”

  4. comment: “Testing”

  5. commenterPhoto: “https://lh3.googleusercontent.com/a-/AAuE7mDMpdVCic53F1pSMRr3gCCDpk77MPLXwPSjTfC9Qg

  6. dateString: 1583874078715

  7. document_ref: “G7CuGyQznm0fvxCIC0NO”

    1. likes: Array(2)
  8. 0:

  9. userEmail: "marcos.c.allencar@gmail.com"

  10. proto: Object

  11. 1:

  12. userEmail: "hello@catalizr.com"

  13. proto: Object

  14. length: 2

  15. proto: Array(0)

  16. userEmail: "marcos.c.allencar@gmail.com"

  17. userId: “1REdv9YQpBf3GDNyfAqdtwbUXxu2”

  18. userNeighborhood: “Sumaré”

  19. proto: Object


#11

Does RS support Array fields? I mean, I have reconsidered my approach and compile the code again without any code trying to retrieve the Array value using Firestore console. Just like any other field pointing the text to the likes Array data runtime linkage. The result instead of data is the number 28? What is written is [{userId = 1REdv9YQpBf3GDNyfAqdtwbUXxu2}]
I’m confused :frowning:


#12

Hi, array fields seems to return as string which is looks quite weird so I would say that at the moment Firebase plugins are not supporting arrays at all.

P.S. I managed to get the Favorites logic to work but it requires some custom coding in the exported code.

My logic is something like this:

  1. In my main list item component I load data sheet which loads all users favorites from Firebase sub collection (users//userFavorites)

  2. I have global variable favoriteID which is empty until favorite is found.

  3. I loop through the userFavorites array and check if this item is found from user favorites. If it is found then I return it to favoriteID variable

  4. I handle Favorite button component’s state based on the value in favoriteID. If it has value then this item is users favorite.

Inside Favorite button component I have two states. One when it is not favorite and one when it is favorite. When user clicks favorite it adds new row to favoriteInputs data sheet which is another data sheet connected to userfavorites sub collection.

Wehn user clicks “unfavorite button” the I have custom script which deletes document from userfavorites subcollection.

This is definitely not that simple logic to create with vanilla Firestore.


#13

Hi. It’s a JSON string. If one can write, update and delete a value inside an object array, retrieve in React studio Firebase plugin should be simple right?


#14

Yeah it is JSON string but it looks like the Plugin does not understand it the way it probably should. We’re. busy with other projects at the moment so If you have Firebase plugin modifications to offer we can test and check them and perhaps even publish the update to everyone.


#15

I deployed my test project to Firebase hosting: https://slackclone-c5e5d.firebaseapp.com

It showcases the my custom solution for saving favorites into userFavorites collection. Project does contain bug if you click the image in the list but adding and removing favorites for user is working.


#16

Great. That’s what I’m trying to do with React Studio for last two weeks. I thought it would be easy, considering all I did till now. Learning a lot but at the same getting frustrated. :frowning:
Would you share the file? if I can improve it, I’ll share back the solution

take care! tough times


#17

Actually the React Studio project file will not help you much because it is missing all the custom code I wrote. There’s not that much custom code but still it is something one cannot include directly into RS project.

I’ll check if I can share you the Custom code somehow here or via email.

Yeah it’s going to be tough times here in Finland as well.


#18

Thank you Antti, I appreciate that.


#19

Hi. I think I’m almost there. I hope :slight_smile: The trick to retrieve the value so React can render it, is to turn the value through JSON.stringify(input).

var docRef = db.collection(Userposts/${postID}/postComments/).where(“likes”, “==”, {userId: ‘userId’})
return JSON.stringify(input);

Still, I need help to finish this task. I have to change the state of the button if the value is there.
Having a component with two states, I tried some scripts but it didn’t work:
Here’s how to add and remove values using the method arrayRemove and arrayUnion

var db = firebase.firestore();

var postID = this.props.appActions.dataSlots['ds_SlotpostID'];
var commentId = this.props.appActions.dataSlots['ds_SlotCommentId'];
var userId = this.props.appActions.dataSlots['ds_SlotUserID'];
var docRef = db.collection(`Userposts/${postID}/postComments`).doc(commentId);
        
// Atomically add a new region to the "likes" array field.
docRef.update({likes: firebase.firestore.FieldValue.arrayUnion({userId})
});

Still, I have to change the state of the button if the value is there.

I tried some scripts like but it didn’t work:

var userId = this.props.appActions.dataSlots[‘ds_SlotUserID’];
var likes = JSON.stringify(this.props.likes);
if (userId === likes) {
return 1;
} else {
return 0;
}


#20

I think you should simply loop trough the likes array and return 1 in case the item is found.