0

I have two tables in Firebase: Vouchers & ClaimedVouchers. I am trying to display the vouchers that do not appear in the ClaimedVouchers table. So, I have a query that gets all of the vouchers, then another that checks if they're claimed and if it's claimed or not the function should return either true or false:

This is isClaimedAPI.js

    export default () => {
      var result;
    
      async function isClaimed(voucher, user) {
        var db = Firebase.firestore();
        console.log("voucher");
        await db
    .collection("ClaimedVoucher")
    .where("voucherID", "==", voucher)
    .where("userID", "==", user)
    .get()
    .then(function (querySnapshot) {
      if (querySnapshot.empty === false) {
        result = true;
      } else {
        result = false;
      }
    })
    .catch(function (error) {
      console.log("Error getting documents: ", error);
    });
  console.log(result, "this is result");

  return result;
      //Call when component is rendered
      useEffect(() => {
        isClaimed().then((result) => setResult(result));
      }, []);
    
      return [isClaimed];

    
 

And then in my main function:

 var user = Firebase.auth().currentUser;
    var uid = user.uid;
    const [getVouchers, voucherList, errorMessage] = getVouchersAPI(ID); //List of vouchers to be checked
    const [isClaimed] = isClaimedAPI();
    
    
    return(
<ScrollView>
    {voucherList.map((item, index) => {
              var voucher = item;
              
              var isVoucherClaimed = isClaimed(voucher.voucherID, uid);
              console.log("this is result, ", isVoucherClaimed);
              if (
                isVoucherClaimed === false
              ) {
                  return <Text>{item.name}<Text>
                }
    })}
  </ScrollView>
 );

Now nothing happens and I receive the following warning: [Unhandled promise rejection: FirebaseError: Function Query.where() requires a valid third argument, but it was undefined.] but I think this is unrelated to the issue.

kiermcguirk
  • 3
  • 1
  • 3
  • It seems you are not using state in the customhook isClaimedAPI that you have developed. Please use result as state in isClaimedAPI – Asutosh Aug 01 '20 at 13:36
  • Hi, I've updated to store the result in state - i've edited my initial comment - could you please look at it again? There are additional issues now. – kiermcguirk Aug 01 '20 at 14:30
  • do not setState inside the async function, just return the result from ther. Inside useEffect, try ` isClaimed().then((result)=>setResult(result)) ` – Asutosh Aug 01 '20 at 14:33
  • Ah I see what you mean. However, I think I'm still doing something wrong. I'm not sure how isClaimed will have access to the setResult hook that's in the scope of the main program? – kiermcguirk Aug 01 '20 at 15:15
  • I have given a codesandox in the answer, please follow that how to use setState in a custom hook fetching data from a async function – Asutosh Aug 01 '20 at 15:29

2 Answers2

2

Your isClaimed is an async function, meaning that it returns a promise - or a delayed result. If you want to wait for the result when calling isClaimed, you'll need to use await:

await isClaimed(voucher.voucherID, uid);
console.log(result);

This most likely isn't possible in a render method though, which is why (as Asutosh commented) you'll have to store the result in the state, and then use the state in your render method.

So the setup you need is:

  • Start the loading of all your data in componentDidMount or with useEffect.
  • When the data is loaded, put it in the state with setState or a state hook.
  • Use the data in your render method.

For a few examples of this, see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Hi, I've updated to store the result in state - i've edited my initial comment - could you please look at it again? There are additional issues now. – kiermcguirk Aug 01 '20 at 14:29
  • Please don't modify your question in this way, as there's now a mismatch between the question and the answers. Since you applied the approach I recommended, you now have a different problem. Please roll back your question to the original problem, and post a new question for the new problem so that (possibly somebody else) can help/ – Frank van Puffelen Aug 01 '20 at 18:32
0

Just to highlight how you can use isClaimed as hoook and set state calling a async function inside it. Later use the above hook in a react component. Please follow below sanbox.

https://codesandbox.io/s/confident-cray-4g2md?file=/src/App.js

Asutosh
  • 1,775
  • 2
  • 15
  • 22
  • Hi thanks for your example. I've tried following what you've done, I've edited my original comment if you could take a look please - your help is much appreciated. – kiermcguirk Aug 01 '20 at 15:49
  • @kiermcguirk I still se the original question does not implement useState inside the hook. – Asutosh Aug 02 '20 at 03:37