Firebase RecaptchaVerifier.clear()没有效果

z18hc3ub  于 2023-06-24  发布在  其他
关注(0)|答案(7)|浏览(94)

我有一个react web应用程序,我想实现电话认证。我已经根据文档和示例初始化了recaptchaVerifier。但是,如果我想再次提交表单(说是因为错误)。我收到错误:Error: reCAPTCHA has already been rendered in this element
我尝试使用.clear方法删除验证程序,但似乎没有效果。Bellow是示例代码。
我是不是忽略了什么?
谢谢你。

class PhoneAuth extends React.Component {
  static contextTypes = {
    firebase: PropTypes.object.isRequired,
  };

  state = {
    phone: '',
  }

  onChangeHandler = (e) => {
    this.setState({
      [e.target.name]: e.target.value,
    })
  }

  onPhoneLoginSubmit = (e) => {
    const { onVerificationSend } = this.props
    const {phone} = this.state
    const {firebase }=this.context

    e.preventDefault()

    this.applicationVerifier = new firebase.auth.RecaptchaVerifier(
      'recaptcha-container',
      { size: 'invisible' }
    );

    firebase.auth().signInWithPhoneNumber(phone, this.applicationVerifier)
      .then((result) => {
        onVerificationSend(result.verificationId)
        this.applicationVerifier.clear()
      })
      .catch (error => {
        this.setState({formError: error})
        this.applicationVerifier.clear()
      })
  }

  render() {
    const { intl } = this.props;
    const { phone, formError } = this.state

    return (
      <div>
      <form onSubmit={this.onPhoneLoginSubmit} name="phone-signin" method="post">
              <input
                id="phone"
                name="phone"
                type="phone"
                onChange={this.onChangeHandler}
                value={phone}
              />
              <label className="input__label" htmlFor="email">
               phone number
              </label>

            {formError && (
              <p >
                {formError.code}
              </p>
            )}

            <button
              type="submit"
            >
              sign in
            </button>
          </form>
          <div id="recaptcha-container"></div>
      </div>
    )
  }
}
7d7tgy0s

7d7tgy0s1#

所以,我想办法了。问题出在clear()方法上--它工作正常。但我必须自己从头开始重新创建验证码容器。医生没说清楚,所以我很困惑。在文档中有:

  • 清除页面中的reCAPTCHA小部件并销毁当前示例。*

所以我认为它将通过方法被删除。
所以,现在我在render方法中有这样的代码:

<div ref={ref => this.recaptchaWrapperRef = ref}>
  <div id="recaptcha-container"></div>
</div>

然后在submit回调中:

if (this.applicationVerifier && this.recaptchaWrapperRef) {
  this.applicationVerifier.clear()
  this.recaptchaWrapperRef.innerHTML = `<div id="recaptcha-container"></div>`
}

// Initialize new reCaptcha verifier
this.applicationVerifier = new firebase.auth.RecaptchaVerifier(
  'recaptcha-container',
  { size: 'invisible' }
);

这是我唯一能做出React的方法。如果有人还有更好的方法来做这件事,请随时张贴。我认为这是相当丑陋的(对于React)。

dauxcl2d

dauxcl2d2#

如果您使用Firebase v9,请使用此代码。

if (this.window.recaptchaVerifier) {
  this.window.recaptchaVerifier.recaptcha.reset(
    this.window.recaptchaWidgetId
  );
} else {
  this.window.recaptchaVerifier = new RecaptchaVerifier(
    'sign-in',
    {
      size: 'invisible',
      callback: () => {
        // sign in with phone number
      },
    },
    getAuth()
  );
  this.window.recaptchaWidgetId =
    await this.window.recaptchaVerifier.render();
}
liwlm1x9

liwlm1x93#

onPhoneLoginSubmit()方法外部使用captchaVariifier
不使用

this.applicationVerifier

this.applicationVerifier = new firebase.auth.RecaptchaVerifier(
      'recaptcha-container',
      { size: 'invisible' }
    );

而是使用window.rectchaVerifier并删除.clear()

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier(
        "recaptcha-container",
        {
          size: "invisible"
        }
      );

onPhoneLoginSubmit = (e) => {
firebase.auth().signInWithPhoneNumber(phone, window.recaptchaVerifier)
  .then((result) => {
    onVerificationSend(result.verificationId)

  })
  .catch (error => {
    this.setState({formError: error})

  })
}

然后使用setTimeout()函数,延迟1或2秒,如果不使用setTimeout(),则recaptcha容器<div id="recaptcha-container"></div>将在此代码之后执行,这将产生错误
因此使用setTimeout(),下面给出示例

componentWillMount(){
 setTimeout(() => {
  window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier(
    "recaptcha-container",
    {
      size: "invisible"
    }
  );
 }, 2000);
}
 onPhoneLoginSubmit = (e) => {
firebase.auth().signInWithPhoneNumber(phone, window.recaptchaVerifier)
  .then((result) => {
    onVerificationSend(result.verificationId)

  })
  .catch (error => {
    this.setState({formError: error})

  })
}
ffscu2ro

ffscu2ro4#

我对React也有同样的问题。但是有一个Ref的问题。所以我使用父div元素的Id创建了一个新示例

<div ref={ref => this.recaptchaWrapperRef = ref}>
   <div id="recaptcha-container"></div>
</div>

在submit回调中添加这个。

document.getElementById("recaptcha-container").innerHTML = "<div id='recaptcha'></div>";
inn6fuwd

inn6fuwd5#

我通过使用state有条件地渲染元素来实现这一点:在尝试登录之前呈现,并在每次尝试结束时取消呈现。

const DoSignin = () => {

  // trigger verification by setVerifying(true)
  const [verifying, setVerifying] = useState(false)
  useEffect(() => {
    if (!verifying) return

    let verifier = new RecaptchaVerifier(
      "recaptcha-container",
      {size: "invisible"},
      auth,
    )

    // signInWithPhoneNumber plus all your logic
    .finally(() => setVerifying(false))
  },[verifying])

  return (
    ...
    {verifying && <div id="recaptcha-container" />}
    ...
  )
}

我使用useEffect触发验证,监视verifying的更改,以确保在useEffect触发时,我们将装载隐藏的recaptcha的元素被装载。

falq053o

falq053o6#

首先在你的dom中创建一个验证码父项:-
<span id="captcha-parent" />
在调用函数时创建具有diff id验证码元素之后
你可以创建一个动态的captcha元素当你再次调用这个函数时,当出现错误时,你可以用下面的代码删除captcha容器。

const recaptchaParent = document.getElementById("captcha-parent");
       if (recaptchaParent) 
{ recaptchaParent.innerHTML = "<span  id=${localMobileNumber} />"

const recaptchaContainer=document.getElementById(localMobileNumber)
    if (recaptchaContainer) { recaptchaContainer.remove();}
8ljdwjyq

8ljdwjyq7#

只需在catch中使用window.recaptchaVerifier.reset()即可

const signInWithPhoneNumber = (fullMobile) => {
return new Promise((resolve, reject) => {
  auth.signInWithPhoneNumber(fullMobile, window.recaptchaVerifier).then(res => {
    resolve(res)
  })
    .catch(error => {
      console.log(error)
      window.recaptchaVerifier.reset()
      reject(error)
    })
})

}

相关问题