0

I'm trying to save record into database, if this record is not in user's profile (he did not discover this place) but also this record exists in collection of all places.

I'm using Expo react native and I think my problem is, that if condition will execute before functions recordInUsersAccount and recordInGlobalDatabase . Is there any way how to ensure execution after these two functions are copleted? In functions I'm rewriting variables in state={}, so I can check them below. (I tried .then() and await, async but I was not succesful).

Thank you very much.

saveScannedQrCode(idOfPlace) {

     this.recordInUsersAccount(idOfPlace);
     this.recordInGlobalDatabase(idOfPlace);

    if (!this.state.placeAlreadyScanned && this.state.placeExistInDatabase) {  
      // we will add this record into database
    } else {      
          // we will NOT add this record into database
  }
 }

This is the code of functions:

recordInUsersAccount(idOfPlace) {
        const userId = auth.currentUser.uid;
        const usersRef = db
          .collection("placesExploredByUsers") // default
          .doc("mUJYkbcbK6OPrlNuEPzK") // default
          .collection("s53sKFeF5FS0DjuI2cdO1Rp9sCS2") // uid
          .doc(idOfPlace); // id of place
    
        usersRef.get().then((docSnapshot) => {
          if (docSnapshot.exists) {
            this.setState({
              placeAlreadyScanned: true, // place is in user's database
            });
          } else {
            this.setState({
              placeAlreadyScanned: false, // place is NOT in user's database
            });
          }
        });
      }
      recordInGlobalDatabase(idOfPlace) {
        const usersRef = db
          .collection("databaseOfPlaces") // default
          .doc(idOfPlace); // id of place
    
        usersRef.get().then((docSnapshot) => {
          if (docSnapshot.exists) {
            this.setState({
              placeExistInDatabase: true, // place is in global database of places
            });
          } else {
            this.setState({
              placeExistInDatabase: false, // place is NOT in global database of places
            });
          }
        });
      }
2
  • Can you post the code of the functions that you want to await for? Commented Mar 2, 2021 at 14:38
  • sure, I updated my post Commented Mar 2, 2021 at 15:00

1 Answer 1

0

The problem with the code is that setState in React is async, and you're trying to check the values straight after executing the functions which modify the state.

Assuming that your methods work fine and do what they're supposed to do, you could do something like:

  1. Leave your methods as they are right now, modifying the state.

  2. Call saveScannedQRCode as your are doing now, triggering both of the helper methods.

  3. Instead of checking the state right after calling them, you could do that in the componentDidUpdate lifecycle hook.

     componentDidUpdate(prevProps, prevState) {
       if (prevState.placeExistInDatabase !== this.state.placeExistInDatabase && prevState.placeAlreadyScanned !== this.state.placeAlreadyScanned) {
         // do something here - at this point state is already updated and ready to use.
         // you could check for the values you're waiting for to update the DB, else not do anything.
       }
     }
    
      saveScannedQrCode(idOfPlace) {
        this.recordInUsersAccount(idOfPlace);
        this.recordInGlobalDatabase(idOfPlace);
      }
    

One thing - be sure to reset the state (e.g. set it to null) once you've processed the update, this way your componentDidUpdate hook won't have any problems and your strict equality will be fine.

Sign up to request clarification or add additional context in comments.

4 Comments

If I implement it like this, but seems like it is not working: I'm getting default value of variables or I get 'spamed' by alerts. Maybe I should provide whole code as function should fire after scanning QR code?
Change your condition by || so that it checks whenever (if your requests return at different time, then the condition I've put might not be true) and then do your check. Else, you could use the callback of the setState.
I tried to put || condition but in this case, only first method called in function saveScannedQrCode will change its state from null to true/false and second will remain null. If I leave condition as it is (&&) it won't even print the alert I put inside componentDidUpdate to check if it's working.
Hey, so I mannaged to get it running. I used your advice about componentDidUpdate but I checked if both variables (placeAlreadyScaned and placeExistsInDatabase) are not null and then perform action. So thanks for your advice :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.