反应不可见的 reCAPTCHA

React Invisible reCAPTCHA

我正在使用 react-google-recaptcha 来实现不可见的 ReCaptcha,将 ref 传递给 ReCAPTCHA 组件并在 componentDidMount 中执行 this._reCaptchaRef.current.execute()https://stackblitz.com/edit/react-invisbile-recaptcha 展示了一个使用 reCaptcha 的表单。

传递给验证码组件的 onChange 回调会将验证码的值设置到状态中。初始渲染验证码值被设置为状态,一切似乎都工作正常,点击 submit 按钮,状态值被打印到控制台上。

几秒钟后,如果我们点击提交并查看控制台,验证码的值为空。我尝试比较传递给 onChange 的值,如果它为空,我将调用 this._reCaptchaRef.current.execute() 但是当值为 null 并且我们调用该函数但第一个 submit 时问题出现空。

如何为提交按钮调用 Recaptcha 并将验证码的值传递给回调函数?

大意是recaptcha token只在一段时间内有效。这是为了使令牌不容易被其他计算机系统猜到。

您应该只执行它 onSubmit,而不是在安装时执行验证码,因此用户在看到验证码时会填写表格。

handleSubmit(event) {
  event.preventDefault();
  this._reCaptchaRef.current.execute()
}

这将依次触发 onChange 处理程序(或 onError 处理程序),您可以从那里提交表单。

但如果你想以某种方式保留它在componentDidMount,你可以选择重置验证码并再次执行它。

redoCaptcha() {
  this._reCaptchaRef.current.reset();
  this._reCaptchaRef.current.execute();
}
render() {
 ...
 <ReCAPTCHA
   onExpired={this.redoCaptcha}
 />
}
import ReCAPTCHA from 'react-google-recaptcha';

const DELAY = 1500;
class Form extends React.Component {
constructor (props) {
    super(props);

    this.state = {
      value: '',
      load: false,
      expired: 'false',
      recaptchaLoaded: false
    };

    this._onSubmit = this._onSubmit.bind(this);
    this._reCaptchaRef = React.createRef();
  }

  componentDidMount () {
    setTimeout(() => {
      this.setState({load: true});
    }, DELAY);
  }

sendData (endpoint, formData) {
    //--
    //---
    //---
    newFormData.append('recaptcha-token', this.state.value);
    //----
}

handleChange (value) {
  this.setState({value});
  if (this.state.value === null) this.setState({expired: 'true'});
}

asyncScriptOnLoad () {
  this.setState({recaptchaLoaded: true});
}

@validateAll
async _onSubmit (valid, e) {
    e.preventDefault();
    await this._reCaptchaRef.current.executeAsync();
    //----
    //---
}

render () {
    {this.state.load && googleSiteKey && (
                  <ReCAPTCHA
                    style={{display: 'inline-block'}}
                    theme="dark"
                    size="invisible"
                    ref={this._reCaptchaRef}
                    sitekey={googleSiteKey}
                    onChange={this.handleChange.bind(this)}
                    asyncScriptOnLoad={this.asyncScriptOnLoad.bind(this)}
                  />
                )}
    <button className="cta--primary" disabled={!this.state.recaptchaLoaded}>{hasForm && (<Icon icon="rightarrow" fillColor="#fff" />)}{submit}</button>
    //------
    //---
}

module.exports = Form;

//-----------------------------------------------------
//for old react version remove React.createRef();
//add below line:

import ReCAPTCHA from 'react-google-recaptcha';

const DELAY = 1500;
class Form extends React.Component {
constructor (props) {
    super(props);

    this.state = {
      value: '',
      load: false,
      expired: 'false',
      recaptchaLoaded: false
    };

    this._onSubmit = this._onSubmit.bind(this);
  }
componentDidMount () {
    setTimeout(() => {
      this.setState({load: true});
    }, DELAY);
}
sendData (endpoint, formData) {
    //--
    //---
    //---
    const newFormData = new FormData();
    newFormData.append('recaptcha-token', this.state.value);
}

handleChange (value) {
    this.setState({value});
    if (this.state.value === null) this.setState({expired: 'true'});
}

asyncScriptOnLoad () {
    this.setState({recaptchaLoaded: true});
}

@validateAll
  async _onSubmit (valid, e) {
    e.preventDefault();
    await this.recaptchaRef.executeAsync();
    //----
    //---
}

render () {
    {this.state.load && googleSiteKey && (
                  <ReCAPTCHA
                    style={{display: 'inline-block'}}
                    theme="dark"
                    size="invisible"
                    ref={(el) => { this.recaptchaRef = el; }}
                    sitekey={googleSiteKey}
                    onChange={this.handleChange.bind(this)}
                    asyncScriptOnLoad={this.asyncScriptOnLoad.bind(this)}
                  />
                )}
    <button className="cta--primary" disabled={!this.state.recaptchaLoaded}>{hasForm && (<Icon icon="rightarrow" fillColor="#fff" />)}{submit}</button>
    //------
    //---
}