【问题标题】:How to use useEffect inside map function?如何在 map 函数中使用 useEffect?
【发布时间】:2020-11-22 02:53:46
【问题描述】:

我在 Firebase 中有两个表:Vouchers 和 ClaimedVouchers。我正在尝试显示未出现在 ClaimedVouchers 表中的凭证。所以,我有一个获取所有凭证的查询,然后是另一个检查它们是否被认领以及是否被认领的函数应该返回 true 或 false:

这是 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];

    
 

然后在我的主要功能中:

 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>
 );

现在什么都没有发生,我收到以下警告:[未处理的承诺拒绝:FirebaseError:函数 Query.where() 需要有效的第三个参数,但它未定义。] 但我认为这与问题无关。

【问题讨论】:

  • 您开发的自定义钩子 isClaimedAPI 中似乎没有使用状态。请使用结果作为 isClaimedAPI 中的状态
  • 嗨,我已经更新以将结果存储在状态中 - 我已经编辑了我的初始评论 - 你能再看一下吗?现在还有其他问题。
  • 不要在异步函数内部设置状态,只返回结果。在 useEffect 中,尝试 `isClaimed().then((result)=>setResult(result)) `
  • 啊,我明白你的意思了。但是,我认为我仍然做错了什么。我不确定 isClaimed 将如何访问主程序范围内的 setResult 挂钩?
  • 我已经在答案中给出了一个codesandox,请按照如何在自定义钩子中使用setState从异步函数中获取数据

标签: javascript reactjs firebase react-native google-cloud-firestore


【解决方案1】:

您的 isClaimed 是一个 async 函数,这意味着它返回一个承诺 - 或延迟的结果。如果要在调用isClaimed时等待结果,则需要使用await

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

这很可能在渲染方法中是不可能的,这就是为什么(正如 Asutosh 评论的那样)您必须将结果存储在状态中,然后在渲染方法中使用状态。

所以你需要的设置是:

  • 开始加载componentDidMountuseEffect 中的所有数据。
  • 加载数据时,将其置于带有setState或状态挂钩的状态。
  • 在渲染方法中使用数据。

有关这方面的一些示例,请参阅:

【讨论】:

  • 嗨,我已经更新以将结果存储在状态中 - 我已经编辑了我的初始评论 - 你能再看一下吗?现在还有其他问题。
  • 请不要以这种方式修改您的问题,因为现在问题和答案不匹配。由于您应用了我推荐的方法,因此您现在遇到了不同的问题。请将您的问题回滚到原始问题,并针对新问题发布一个新问题,以便(可能是其他人)可以提供帮助/
【解决方案2】:

只是为了强调如何使用 isClaimed 作为钩子并设置状态调用其中的异步函数。稍后在反应组件中使用上述钩子。请关注下面的 sanbox。

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

【讨论】:

  • 您好,感谢您的示例。我已经尝试按照您的操作进行操作,如果您可以看一下,我已经编辑了我的原始评论 - 非常感谢您的帮助。
  • @kiermcguirk 我仍然认为原来的问题没有在钩子内实现 useState。
猜你喜欢
  • 1970-01-01
  • 2021-11-03
  • 2020-10-09
  • 2021-05-16
  • 1970-01-01
  • 2019-12-02
  • 2020-09-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多