我怎样才能让 useState 立即更新

时间:2021-03-03 19:47:49

标签: reactjs firebase google-cloud-firestore

有一个表单,用户填写此信息(如电子邮件和密码),然后点击提交按钮开始付款流程。但是在我让该人继续之前,我需要检查用户是否已经在数据库中拥有具有相同电子邮件地址的电子邮件。当我执行 setRetrievedEmailAddress 并将我检索的电子邮件地址(如果存在)设置为变量retrieveedEmailAddress 时,它会立即更新,但是当我第二次单击状态更改的按钮时,它会立即更新,如下所示下面的屏幕截图。我不能在事件处理程序中使用 useEffect 钩子,所以这是不可能的。我需要立即更新状态,否则此人将继续付款过程并最终支付两次,因为他已经在我们这里有一个帐户。所以我的问题是,如何立即更新状态?

enter image description here

g.add_legend(loc=9)

4 个答案:

答案 0 :(得分:1)

发生这种情况是因为您正在调用异步调用,因此当您调用 console.log(retrievedEmailAddress) 时,信息尚未到达。因此,满足您要求的最佳方法是在答案中进行验证:

  database.collection("users").where("email", "==", "nonpaidmembership@gmail.com")
      .get()
      .then((querySnapshot) => {
        if (querySnapshot.exists) {}
          querySnapshot.forEach((doc) => {
            if (doc.exists) {
              setRetrievedEmailAddress(doc.data().email);
              console.log(doc.id, " => ", doc.data().email);
              //here is safe to validate your data
              if (doc.data().email != null) {
                     setError('User Already exists, please choose a different email');
                     console.log("user already exists");
              }
              else {
                     //Start payment Process
              }
            }
            else {
              console.log("doc doesnt exist");
            }
            
          });
      })
      .catch((error) => {
          console.log("Error getting documents: ", error);
      });  
      console.log(retrievedEmailAddress); // here the information will no be present the first time

答案 1 :(得分:0)

所以,您的问题是 setRetrievedEmailAddress 需要一些时间来更新 retrievedEmailAddress

试试这个...

setRetrievedEmailAddress(prevState => (doc.data().email));

答案 2 :(得分:0)

setState 是异步的,你在更新它的函数中没有得到它的更新值, 创建一个已验证的状态;

  const [verified, setVerified] = useState(false);

使用下面提到的 useEffect 钩子

useEffect(() => {
 if(verified){
 // proceed to payment
 // ....

 // at the end don't forget to setVerified(false)


  }
 }, [verified])

答案 3 :(得分:0)

您正在使用异步函数... 所以应该在请求前加上 await 关键字

await database.collection("users").where("email", "==", "nonpaidmembership@gmail.com")
  .get()

此外,在任何情况下,您都不会将 retrievedEmailAddress 设置为 null...这将是有问题的 对于场景

  • 用户输入已经存在的电子邮件 ID(电子邮件存储在检索的电子邮件地址中)然后
  • 用户输入的电子邮件 ID 不存在(但检索的电子邮件地址未更新,因此 if (retrievedEmailAddress != null) 将为真且付款流程不会开始)